1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2015 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 Indexed blend operation tests (GL_EXT_draw_buffers_indexed)
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fDrawBuffersIndexedTests.hpp"
25
26 #include "gluContextInfo.hpp"
27 #include "gluDrawUtil.hpp"
28 #include "gluObjectWrapper.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "gluShaderProgram.hpp"
31 #include "gluStrUtil.hpp"
32 #include "gluTextureUtil.hpp"
33
34 #include "sglrReferenceUtils.hpp"
35
36 #include "rrMultisamplePixelBufferAccess.hpp"
37 #include "rrRenderer.hpp"
38
39 #include "glwEnums.hpp"
40 #include "glwFunctions.hpp"
41
42 #include "tcuEither.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "tcuMaybe.hpp"
45 #include "tcuResultCollector.hpp"
46 #include "tcuTestLog.hpp"
47 #include "tcuTexture.hpp"
48 #include "tcuTextureUtil.hpp"
49 #include "tcuVector.hpp"
50 #include "tcuVectorUtil.hpp"
51
52 #include "deRandom.hpp"
53 #include "deArrayUtil.hpp"
54 #include "deStringUtil.hpp"
55 #include "deUniquePtr.hpp"
56
57 #include "deInt32.h"
58
59 #include <string>
60 #include <vector>
61
62 using tcu::BVec4;
63 using tcu::Either;
64 using tcu::IVec2;
65 using tcu::IVec4;
66 using tcu::Maybe;
67 using tcu::TestLog;
68 using tcu::TextureFormat;
69 using tcu::TextureLevel;
70 using tcu::UVec4;
71 using tcu::Vec2;
72 using tcu::Vec4;
73 using tcu::just;
74
75 using std::string;
76 using std::vector;
77
78 using sglr::rr_util::mapGLBlendEquation;
79 using sglr::rr_util::mapGLBlendFunc;
80 using sglr::rr_util::mapGLBlendEquationAdvanced;
81
82 namespace deqp
83 {
84 namespace gles31
85 {
86 namespace Functional
87 {
88 namespace
89 {
90
91 typedef deUint32 BlendEq;
92
isAdvancedBlendEq(BlendEq eq)93 bool isAdvancedBlendEq (BlendEq eq)
94 {
95 switch (eq)
96 {
97 case GL_MULTIPLY_KHR: return true;
98 case GL_SCREEN_KHR: return true;
99 case GL_OVERLAY_KHR: return true;
100 case GL_DARKEN_KHR: return true;
101 case GL_LIGHTEN_KHR: return true;
102 case GL_COLORDODGE_KHR: return true;
103 case GL_COLORBURN_KHR: return true;
104 case GL_HARDLIGHT_KHR: return true;
105 case GL_SOFTLIGHT_KHR: return true;
106 case GL_DIFFERENCE_KHR: return true;
107 case GL_EXCLUSION_KHR: return true;
108 case GL_HSL_HUE_KHR: return true;
109 case GL_HSL_SATURATION_KHR: return true;
110 case GL_HSL_COLOR_KHR: return true;
111 case GL_HSL_LUMINOSITY_KHR: return true;
112 default:
113 return false;
114 }
115 }
116
117 struct SeparateBlendEq
118 {
SeparateBlendEqdeqp::gles31::Functional::__anon169a63d40111::SeparateBlendEq119 SeparateBlendEq (BlendEq rgb_, BlendEq alpha_)
120 : rgb (rgb_)
121 , alpha (alpha_)
122 {
123 }
124
125 BlendEq rgb;
126 BlendEq alpha;
127 };
128
129 struct BlendFunc
130 {
BlendFuncdeqp::gles31::Functional::__anon169a63d40111::BlendFunc131 BlendFunc (deUint32 src_, deUint32 dst_)
132 : src (src_)
133 , dst (dst_)
134 {
135 }
136
137 deUint32 src;
138 deUint32 dst;
139 };
140
141 struct SeparateBlendFunc
142 {
SeparateBlendFuncdeqp::gles31::Functional::__anon169a63d40111::SeparateBlendFunc143 SeparateBlendFunc (BlendFunc rgb_, BlendFunc alpha_)
144 : rgb (rgb_)
145 , alpha (alpha_)
146 {
147 }
148
149 BlendFunc rgb;
150 BlendFunc alpha;
151 };
152
153 typedef deUint32 DrawBuffer;
154
155 struct BlendState
156 {
BlendStatedeqp::gles31::Functional::__anon169a63d40111::BlendState157 BlendState (void) {}
158
BlendStatedeqp::gles31::Functional::__anon169a63d40111::BlendState159 BlendState (const Maybe<bool>& enableBlend_,
160 const Maybe<Either<BlendEq, SeparateBlendEq> >& blendEq_,
161 const Maybe<Either<BlendFunc, SeparateBlendFunc> >& blendFunc_,
162 const Maybe<BVec4>& colorMask_)
163 : enableBlend (enableBlend_)
164 , blendEq (blendEq_)
165 , blendFunc (blendFunc_)
166 , colorMask (colorMask_)
167 {
168 }
169
isEmptydeqp::gles31::Functional::__anon169a63d40111::BlendState170 bool isEmpty (void) const
171 {
172 return (!enableBlend) && (!blendEq) && (!blendFunc) && (!colorMask);
173 }
174
175 Maybe<bool> enableBlend;
176 Maybe<Either<BlendEq, SeparateBlendEq> > blendEq;
177 Maybe<Either<BlendFunc, SeparateBlendFunc> > blendFunc;
178 Maybe<BVec4> colorMask;
179 };
180
setCommonBlendState(const glw::Functions & gl,const BlendState & blend)181 void setCommonBlendState (const glw::Functions& gl, const BlendState& blend)
182 {
183 if (blend.enableBlend)
184 {
185 if (*blend.enableBlend)
186 gl.enable(GL_BLEND);
187 else
188 gl.disable(GL_BLEND);
189 }
190
191 if (blend.colorMask)
192 {
193 const BVec4& mask = *blend.colorMask;
194
195 gl.colorMask(mask.x(), mask.y(), mask.z(), mask.w());
196 }
197
198 if (blend.blendEq)
199 {
200 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
201
202 if (blendEq.is<BlendEq>())
203 gl.blendEquation(blendEq.get<BlendEq>());
204 else if (blendEq.is<SeparateBlendEq>())
205 gl.blendEquationSeparate(blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
206 else
207 DE_ASSERT(false);
208 }
209
210 if (blend.blendFunc)
211 {
212 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
213
214 if (blendFunc.is<BlendFunc>())
215 gl.blendFunc(blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
216 else if (blendFunc.is<SeparateBlendFunc>())
217 gl.blendFuncSeparate(blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
218 else
219 DE_ASSERT(false);
220 }
221
222 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set common blend state.");
223 }
224
setIndexedBlendState(const glw::Functions & gl,const BlendState & blend,deUint32 index)225 void setIndexedBlendState (const glw::Functions& gl, const BlendState& blend, deUint32 index)
226 {
227 if (blend.enableBlend)
228 {
229 if (*blend.enableBlend)
230 gl.enablei(GL_BLEND, index);
231 else
232 gl.disablei(GL_BLEND, index);
233 }
234
235 if (blend.colorMask)
236 {
237 const BVec4 mask = *blend.colorMask;
238
239 gl.colorMaski(index, mask.x(), mask.y(), mask.z(), mask.w());
240 }
241
242 if (blend.blendEq)
243 {
244 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
245
246 if (blendEq.is<BlendEq>())
247 gl.blendEquationi(index, blendEq.get<BlendEq>());
248 else if (blendEq.is<SeparateBlendEq>())
249 gl.blendEquationSeparatei(index, blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
250 else
251 DE_ASSERT(false);
252 }
253
254 if (blend.blendFunc)
255 {
256 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
257
258 if (blendFunc.is<BlendFunc>())
259 gl.blendFunci(index, blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
260 else if (blendFunc.is<SeparateBlendFunc>())
261 gl.blendFuncSeparatei(index, blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
262 else
263 DE_ASSERT(false);
264 }
265
266 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set draw buffer specifig blend state.");
267 }
268
269 class DrawBufferInfo
270 {
271 public:
272 DrawBufferInfo (bool render,
273 const IVec2& size,
274 const BlendState& blendState,
275 const TextureFormat& format);
276
getFormat(void) const277 const TextureFormat& getFormat (void) const { return m_format; }
getSize(void) const278 const IVec2& getSize (void) const { return m_size; }
getBlendState(void) const279 const BlendState& getBlendState (void) const { return m_blendState; }
getRender(void) const280 bool getRender (void) const { return m_render; }
281
282 private:
283 bool m_render;
284 IVec2 m_size;
285 TextureFormat m_format;
286 BlendState m_blendState;
287 };
288
DrawBufferInfo(bool render,const IVec2 & size,const BlendState & blendState,const TextureFormat & format)289 DrawBufferInfo::DrawBufferInfo (bool render, const IVec2& size, const BlendState& blendState, const TextureFormat& format)
290 : m_render (render)
291 , m_size (size)
292 , m_format (format)
293 , m_blendState (blendState)
294 {
295 }
296
clearRenderbuffer(const glw::Functions & gl,const tcu::TextureFormat & format,int renderbufferNdx,int renderbufferCount,tcu::TextureLevel & refRenderbuffer)297 void clearRenderbuffer (const glw::Functions& gl,
298 const tcu::TextureFormat& format,
299 int renderbufferNdx,
300 int renderbufferCount,
301 tcu::TextureLevel& refRenderbuffer)
302 {
303 const tcu::TextureFormatInfo info = tcu::getTextureFormatInfo(format);
304
305 // Clear each buffer to different color
306 const float redScale = float(renderbufferNdx + 1) / float(renderbufferCount);
307 const float blueScale = float(renderbufferCount - renderbufferNdx) / float(renderbufferCount);
308 const float greenScale = float(((renderbufferCount/2) + renderbufferNdx) % renderbufferCount) / float(renderbufferCount);
309 // Alpha should never be zero as advanced blend equations assume premultiplied alpha.
310 const float alphaScale = float(1 + (((renderbufferCount/2) + renderbufferCount - renderbufferNdx) % renderbufferCount)) / float(renderbufferCount);
311
312 switch (tcu::getTextureChannelClass(format.type))
313 {
314 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
315 {
316 const float red = -1000.0f + 2000.0f * redScale;
317 const float green = -1000.0f + 2000.0f * greenScale;
318 const float blue = -1000.0f + 2000.0f * blueScale;
319 const float alpha = -1000.0f + 2000.0f * alphaScale;
320 const Vec4 color (red, green, blue, alpha);
321
322 tcu::clear(refRenderbuffer, color);
323 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
324 break;
325 }
326
327 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
328 {
329 const deInt32 red = deInt32(info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale);
330 const deInt32 green = deInt32(info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale);
331 const deInt32 blue = deInt32(info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale);
332 const deInt32 alpha = deInt32(info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale);
333 const IVec4 color (red, green, blue, alpha);
334
335 tcu::clear(refRenderbuffer, color);
336 gl.clearBufferiv(GL_COLOR, renderbufferNdx, color.getPtr());
337 break;
338 }
339
340 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
341 {
342 const deUint32 red = deUint32(info.valueMax.x() * redScale);
343 const deUint32 green = deUint32(info.valueMax.y() * greenScale);
344 const deUint32 blue = deUint32(info.valueMax.z() * blueScale);
345 const deUint32 alpha = deUint32(info.valueMax.w() * alphaScale);
346 const UVec4 color (red, green, blue, alpha);
347
348 tcu::clear(refRenderbuffer, color);
349 gl.clearBufferuiv(GL_COLOR, renderbufferNdx, color.getPtr());
350 break;
351 }
352
353 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
354 {
355 const float red = info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale;
356 const float green = info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale;
357 const float blue = info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale;
358 const float alpha = info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale;
359 const Vec4 color (red, green, blue, alpha);
360
361 tcu::clear(refRenderbuffer, color);
362 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
363 break;
364 }
365
366 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
367 {
368 const float red = info.valueMax.x() * redScale;
369 const float green = info.valueMax.y() * greenScale;
370 const float blue = info.valueMax.z() * blueScale;
371 const float alpha = info.valueMax.w() * alphaScale;
372 const Vec4 color (red, green, blue, alpha);
373
374 tcu::clear(refRenderbuffer, color);
375 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
376 break;
377 }
378
379 default:
380 DE_ASSERT(DE_FALSE);
381 }
382
383 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer.");
384 }
385
genRenderbuffers(const glw::Functions & gl,const vector<DrawBufferInfo> & drawBuffers,const glu::Framebuffer & framebuffer,const glu::RenderbufferVector & renderbuffers,vector<TextureLevel> & refRenderbuffers)386 void genRenderbuffers (const glw::Functions& gl,
387 const vector<DrawBufferInfo>& drawBuffers,
388 const glu::Framebuffer& framebuffer,
389 const glu::RenderbufferVector& renderbuffers,
390 vector<TextureLevel>& refRenderbuffers)
391 {
392 vector<deUint32> bufs;
393
394 bufs.resize(drawBuffers.size());
395
396 DE_ASSERT(drawBuffers.size() == renderbuffers.size());
397 DE_ASSERT(drawBuffers.size() == refRenderbuffers.size());
398
399 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
400
401 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
402 {
403 const DrawBufferInfo& drawBuffer = drawBuffers[renderbufferNdx];
404 const TextureFormat& format = drawBuffer.getFormat();
405 const IVec2& size = drawBuffer.getSize();
406 const deUint32 glFormat = glu::getInternalFormat(format);
407
408 bufs[renderbufferNdx] = GL_COLOR_ATTACHMENT0 + renderbufferNdx;
409 refRenderbuffers[renderbufferNdx] = TextureLevel(drawBuffer.getFormat(), size.x(), size.y());
410
411 gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
412 gl.renderbufferStorage(GL_RENDERBUFFER, glFormat, size.x(), size.y());
413 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + renderbufferNdx, GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
414 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create renderbuffer.");
415 }
416
417 gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
418
419 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
420 {
421 const DrawBufferInfo& drawBuffer = drawBuffers[renderbufferNdx];
422 const TextureFormat& format = drawBuffer.getFormat();
423
424 clearRenderbuffer(gl, format, renderbufferNdx, (int)refRenderbuffers.size(), refRenderbuffers[renderbufferNdx]);
425 }
426
427 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
428 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
429 }
430
getFixedPointFormatThreshold(const tcu::TextureFormat & sourceFormat,const tcu::TextureFormat & readPixelsFormat)431 Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
432 {
433 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
434 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
435
436 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
437 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
438
439 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
440 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
441
442 const tcu::IVec4 srcBits = tcu::getTextureFormatBitDepth(sourceFormat);
443 const tcu::IVec4 readBits = tcu::getTextureFormatBitDepth(readPixelsFormat);
444
445 return Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
446 }
447
verifyRenderbuffer(TestLog & log,tcu::ResultCollector & results,const tcu::TextureFormat & format,int renderbufferNdx,const tcu::TextureLevel & refRenderbuffer,const tcu::TextureLevel & result)448 void verifyRenderbuffer (TestLog& log,
449 tcu::ResultCollector& results,
450 const tcu::TextureFormat& format,
451 int renderbufferNdx,
452 const tcu::TextureLevel& refRenderbuffer,
453 const tcu::TextureLevel& result)
454 {
455 switch (tcu::getTextureChannelClass(format.type))
456 {
457 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
458 {
459 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
460 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
461 const UVec4 threshold (1, 1, 1, 1);
462
463 if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
464 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
465
466 break;
467 }
468
469 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
470 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
471 {
472 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
473 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
474 const UVec4 threshold (1, 1, 1, 1);
475
476 if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
477 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
478
479 break;
480 }
481
482 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
483 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
484 {
485 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
486 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
487 const Vec4 threshold = getFixedPointFormatThreshold(format, result.getFormat());
488
489 if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
490 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
491
492 break;
493 }
494
495
496 default:
497 DE_ASSERT(DE_FALSE);
498 }
499 }
500
getReadPixelFormat(const TextureFormat & format)501 TextureFormat getReadPixelFormat (const TextureFormat& format)
502 {
503 switch (tcu::getTextureChannelClass(format.type))
504 {
505 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
506 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32);
507
508 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
509 return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32);
510
511 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
512 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
513 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
514
515 default:
516 DE_ASSERT(false);
517 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
518 }
519 }
520
verifyRenderbuffers(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const glu::RenderbufferVector & renderbuffers,const glu::Framebuffer & framebuffer,const vector<TextureLevel> & refRenderbuffers)521 void verifyRenderbuffers (TestLog& log,
522 tcu::ResultCollector& results,
523 glu::RenderContext& renderContext,
524 const glu::RenderbufferVector& renderbuffers,
525 const glu::Framebuffer& framebuffer,
526 const vector<TextureLevel>& refRenderbuffers)
527 {
528 const glw::Functions& gl = renderContext.getFunctions();
529
530 DE_ASSERT(renderbuffers.size() == refRenderbuffers.size());
531
532 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
533
534 for (int renderbufferNdx = 0; renderbufferNdx < (int)renderbuffers.size(); renderbufferNdx++)
535 {
536 const TextureLevel& refRenderbuffer = refRenderbuffers[renderbufferNdx];
537 const int width = refRenderbuffer.getWidth();
538 const int height = refRenderbuffer.getHeight();
539 const TextureFormat format = refRenderbuffer.getFormat();
540
541 tcu::TextureLevel result (getReadPixelFormat(format), width, height);
542
543 gl.readBuffer(GL_COLOR_ATTACHMENT0 + renderbufferNdx);
544 glu::readPixels(renderContext, 0, 0, result.getAccess());
545 GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels from renderbuffer failed.");
546
547 verifyRenderbuffer(log, results, format, renderbufferNdx, refRenderbuffer, result);
548 }
549
550 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
551 }
552
553 static const float s_quadCoords[] =
554 {
555 -0.5f, -0.5f,
556 0.5f, -0.5f,
557 0.5f, 0.5f,
558
559 0.5f, 0.5f,
560 -0.5f, 0.5f,
561 -0.5f, -0.5f
562 };
563
setBlendState(rr::FragmentOperationState & fragOps,const BlendState & state)564 void setBlendState (rr::FragmentOperationState& fragOps, const BlendState& state)
565 {
566 if (state.blendEq)
567 {
568 if (state.blendEq->is<BlendEq>())
569 {
570 if (isAdvancedBlendEq(state.blendEq->get<BlendEq>()))
571 {
572 const rr::BlendEquationAdvanced equation = mapGLBlendEquationAdvanced(state.blendEq->get<BlendEq>());
573
574 fragOps.blendMode = rr::BLENDMODE_ADVANCED;
575 fragOps.blendEquationAdvaced = equation;
576 }
577 else
578 {
579 const rr::BlendEquation equation = mapGLBlendEquation(state.blendEq->get<BlendEq>());
580
581 fragOps.blendMode = rr::BLENDMODE_STANDARD;
582 fragOps.blendRGBState.equation = equation;
583 fragOps.blendAState.equation = equation;
584 }
585 }
586 else
587 {
588 DE_ASSERT(state.blendEq->is<SeparateBlendEq>());
589
590 fragOps.blendMode = rr::BLENDMODE_STANDARD;
591 fragOps.blendRGBState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().rgb);
592 fragOps.blendAState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().alpha);
593 }
594 }
595
596 if (state.blendFunc)
597 {
598 if (state.blendFunc->is<BlendFunc>())
599 {
600 const rr::BlendFunc srcFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().src);
601 const rr::BlendFunc dstFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().dst);
602
603 fragOps.blendRGBState.srcFunc = srcFunction;
604 fragOps.blendRGBState.dstFunc = dstFunction;
605
606 fragOps.blendAState.srcFunc = srcFunction;
607 fragOps.blendAState.dstFunc = dstFunction;
608 }
609 else
610 {
611 DE_ASSERT(state.blendFunc->is<SeparateBlendFunc>());
612
613 fragOps.blendRGBState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.src);
614 fragOps.blendRGBState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.dst);
615
616 fragOps.blendAState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.src);
617 fragOps.blendAState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.dst);
618 }
619 }
620
621 if (state.colorMask)
622 fragOps.colorMask = *state.colorMask;
623 }
624
createRenderState(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const DrawBufferInfo & info)625 rr::RenderState createRenderState (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const DrawBufferInfo& info)
626 {
627 const IVec2 size = info.getSize();
628 rr::RenderState state (rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y())));
629
630 state.fragOps.blendMode = rr::BLENDMODE_STANDARD;
631
632 setBlendState(state.fragOps, preCommonBlendState);
633 setBlendState(state.fragOps, info.getBlendState());
634 setBlendState(state.fragOps, postCommonBlendState);
635
636 if (postCommonBlendState.enableBlend)
637 state.fragOps.blendMode = (*(postCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
638 else if (info.getBlendState().enableBlend)
639 state.fragOps.blendMode = (*(info.getBlendState().enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
640 else if (preCommonBlendState.enableBlend)
641 state.fragOps.blendMode = (*(preCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
642 else
643 state.fragOps.blendMode = rr::BLENDMODE_NONE;
644
645 if (tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT && tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
646 state.fragOps.blendMode = rr::BLENDMODE_NONE;
647
648 return state;
649 }
650
651 class VertexShader : public rr::VertexShader
652 {
653 public:
654 VertexShader (void);
655 virtual void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
656 };
657
VertexShader(void)658 VertexShader::VertexShader (void)
659 : rr::VertexShader (1, 1)
660 {
661 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
662 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
663 }
664
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const665 void VertexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
666 {
667 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
668 {
669 rr::VertexPacket& packet = *packets[packetNdx];
670
671 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
672 packet.outputs[0] = 0.5f * (Vec4(1.0f) + rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx));
673 }
674 }
675
676 class FragmentShader : public rr::FragmentShader
677 {
678 public:
679 FragmentShader (int drawBufferNdx, const DrawBufferInfo& info);
680 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
681
682 private:
683 const int m_drawBufferNdx;
684 const DrawBufferInfo m_info;
685 };
686
FragmentShader(int drawBufferNdx,const DrawBufferInfo & info)687 FragmentShader::FragmentShader (int drawBufferNdx, const DrawBufferInfo& info)
688 : rr::FragmentShader (1, 1)
689 , m_drawBufferNdx (drawBufferNdx)
690 , m_info (info)
691 {
692 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
693
694 switch (tcu::getTextureChannelClass(m_info.getFormat().type))
695 {
696 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
697 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
698 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
699 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
700 break;
701
702 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
703 m_outputs[0].type = rr::GENERICVECTYPE_UINT32;
704 break;
705
706 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
707 m_outputs[0].type = rr::GENERICVECTYPE_INT32;
708 break;
709
710 default:
711 DE_ASSERT(false);
712 };
713 }
714
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const715 void FragmentShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
716 {
717 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
718 {
719 rr::FragmentPacket& packet = packets[packetNdx];
720
721 DE_ASSERT(m_drawBufferNdx >= 0);
722 DE_UNREF(m_info);
723
724 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
725 {
726 const Vec2 vColor = rr::readVarying<float>(packet, context, 0, fragNdx).xy();
727 const float values[] =
728 {
729 vColor.x(),
730 vColor.y(),
731 (1.0f - vColor.x()),
732 (1.0f - vColor.y())
733 };
734
735 switch (tcu::getTextureChannelClass(m_info.getFormat().type))
736 {
737 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
738 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
739 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
740 {
741 const Vec4 color (values[(m_drawBufferNdx + 0) % 4],
742 values[(m_drawBufferNdx + 1) % 4],
743 values[(m_drawBufferNdx + 2) % 4],
744 values[(m_drawBufferNdx + 3) % 4]);
745
746 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
747 break;
748 }
749
750 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
751 {
752 const UVec4 color ((deUint32)(values[(m_drawBufferNdx + 0) % 4]),
753 (deUint32)(values[(m_drawBufferNdx + 1) % 4]),
754 (deUint32)(values[(m_drawBufferNdx + 2) % 4]),
755 (deUint32)(values[(m_drawBufferNdx + 3) % 4]));
756
757 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
758 break;
759 }
760
761 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
762 {
763 const IVec4 color ((deInt32)(values[(m_drawBufferNdx + 0) % 4]),
764 (deInt32)(values[(m_drawBufferNdx + 1) % 4]),
765 (deInt32)(values[(m_drawBufferNdx + 2) % 4]),
766 (deInt32)(values[(m_drawBufferNdx + 3) % 4]));
767
768 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
769 break;
770 }
771
772 default:
773 DE_ASSERT(DE_FALSE);
774 };
775 }
776 }
777 }
778
createVertexAttrib(const float * coords)779 rr::VertexAttrib createVertexAttrib (const float* coords)
780 {
781 rr::VertexAttrib attrib;
782
783 attrib.type = rr::VERTEXATTRIBTYPE_FLOAT;
784 attrib.size = 2;
785 attrib.pointer = coords;
786
787 return attrib;
788 }
789
renderRefQuad(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,vector<TextureLevel> & refRenderbuffers)790 void renderRefQuad (const BlendState& preCommonBlendState,
791 const BlendState& postCommonBlendState,
792 const vector<DrawBufferInfo>& drawBuffers,
793 vector<TextureLevel>& refRenderbuffers)
794 {
795 const rr::Renderer renderer;
796 const rr::PrimitiveList primitives (rr::PRIMITIVETYPE_TRIANGLES, 6, 0);
797 const rr::VertexAttrib vertexAttribs[] =
798 {
799 createVertexAttrib(s_quadCoords)
800 };
801
802 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
803 {
804 if (drawBuffers[drawBufferNdx].getRender())
805 {
806 const rr::RenderState renderState (createRenderState(preCommonBlendState, postCommonBlendState, drawBuffers[drawBufferNdx]));
807 const rr::RenderTarget renderTarget (rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refRenderbuffers[drawBufferNdx].getAccess()));
808 const VertexShader vertexShader;
809 const FragmentShader fragmentShader (drawBufferNdx, drawBuffers[drawBufferNdx]);
810 const rr::Program program (&vertexShader, &fragmentShader);
811 const rr::DrawCommand command (renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, primitives);
812
813 renderer.draw(command);
814 }
815 }
816 }
817
requiresAdvancedBlendEq(const BlendState & pre,const BlendState post,const vector<DrawBufferInfo> & drawBuffers)818 bool requiresAdvancedBlendEq (const BlendState& pre, const BlendState post, const vector<DrawBufferInfo>& drawBuffers)
819 {
820 bool requiresAdvancedBlendEq = false;
821
822 if (pre.blendEq && pre.blendEq->is<BlendEq>())
823 requiresAdvancedBlendEq |= isAdvancedBlendEq(pre.blendEq->get<BlendEq>());
824
825 if (post.blendEq && post.blendEq->is<BlendEq>())
826 requiresAdvancedBlendEq |= isAdvancedBlendEq(post.blendEq->get<BlendEq>());
827
828 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
829 {
830 const BlendState& drawBufferBlendState = drawBuffers[drawBufferNdx].getBlendState();
831
832 if (drawBufferBlendState.blendEq && drawBufferBlendState.blendEq->is<BlendEq>())
833 requiresAdvancedBlendEq |= isAdvancedBlendEq(drawBufferBlendState.blendEq->get<BlendEq>());
834 }
835
836 return requiresAdvancedBlendEq;
837 }
838
genVertexSource(void)839 glu::VertexSource genVertexSource (void)
840 {
841 const char* const vertexSource =
842 "#version 310 es\n"
843 "layout(location=0) in highp vec2 i_coord;\n"
844 "out highp vec2 v_color;\n"
845 "void main (void)\n"
846 "{\n"
847 "\tv_color = 0.5 * (vec2(1.0) + i_coord);\n"
848 "\tgl_Position = vec4(i_coord, 0.0, 1.0);\n"
849 "}";
850
851 return glu::VertexSource(vertexSource);
852 }
853
genFragmentSource(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)854 glu::FragmentSource genFragmentSource (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers)
855 {
856 std::ostringstream stream;
857
858 stream << "#version 310 es\n";
859
860 if (requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers))
861 {
862 stream << "#extension GL_KHR_blend_equation_advanced : require\n"
863 << "layout(blend_support_all_equations) out;\n";
864 }
865
866 stream << "in highp vec2 v_color;\n";
867
868 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
869 {
870 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
871 const TextureFormat& format = drawBuffer.getFormat();
872
873 stream << "layout(location=" << drawBufferNdx << ") out highp ";
874
875 switch (tcu::getTextureChannelClass(format.type))
876 {
877 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
878 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
879 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
880 stream << "vec4";
881 break;
882
883 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
884 stream << "uvec4";
885 break;
886
887 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
888 stream << "ivec4";
889 break;
890
891 default:
892 DE_ASSERT(DE_FALSE);
893 };
894
895 stream << " o_drawBuffer" << drawBufferNdx << ";\n";
896 }
897
898 stream << "void main (void)\n"
899 << "{\n";
900
901 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
902 {
903 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
904 const TextureFormat& format = drawBuffer.getFormat();
905 const char* const values[] =
906 {
907 "v_color.x",
908 "v_color.y",
909 "(1.0 - v_color.x)",
910 "(1.0 - v_color.y)"
911 };
912
913 stream << "\to_drawBuffer" << drawBufferNdx;
914
915 switch (tcu::getTextureChannelClass(format.type))
916 {
917 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
918 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
919 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
920 stream << " = vec4(" << values[(drawBufferNdx + 0) % 4]
921 << ", " << values[(drawBufferNdx + 1) % 4]
922 << ", " << values[(drawBufferNdx + 2) % 4]
923 << ", " << values[(drawBufferNdx + 3) % 4] << ");\n";
924 break;
925
926 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
927 stream << " = uvec4(uint(" << values[(drawBufferNdx + 0) % 4]
928 << "), uint(" << values[(drawBufferNdx + 1) % 4]
929 << "), uint(" << values[(drawBufferNdx + 2) % 4]
930 << "), uint(" << values[(drawBufferNdx + 3) % 4] << "));\n";
931 break;
932
933 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
934 stream << " = ivec4(int(" << values[(drawBufferNdx + 0) % 4]
935 << "), int(" << values[(drawBufferNdx + 1) % 4]
936 << "), int(" << values[(drawBufferNdx + 2) % 4]
937 << "), int(" << values[(drawBufferNdx + 3) % 4] << "));\n";
938 break;
939
940 default:
941 DE_ASSERT(DE_FALSE);
942 };
943 }
944
945 stream << "}";
946
947 return glu::FragmentSource(stream.str());
948 }
949
genShaderSources(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)950 glu::ProgramSources genShaderSources (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers)
951 {
952 return glu::ProgramSources() << genVertexSource() << genFragmentSource(preCommonBlendState, postCommonBlendState, drawBuffers);
953 }
954
renderGLQuad(glu::RenderContext & renderContext,const glu::ShaderProgram & program)955 void renderGLQuad (glu::RenderContext& renderContext,
956 const glu::ShaderProgram& program)
957 {
958 const glu::VertexArrayBinding vertexArrays[] =
959 {
960 glu::VertexArrayBinding(glu::BindingPoint(0), glu::VertexArrayPointer(glu::VTX_COMP_FLOAT, glu::VTX_COMP_CONVERT_NONE, 2, 6, 0, s_quadCoords))
961 };
962
963 glu::draw(renderContext, program.getProgram(), 1, vertexArrays, glu::pr::Triangles(6));
964 }
965
renderQuad(TestLog & log,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const glu::Framebuffer & framebuffer,vector<TextureLevel> & refRenderbuffers)966 void renderQuad (TestLog& log,
967 glu::RenderContext& renderContext,
968 const BlendState& preCommonBlendState,
969 const BlendState& postCommonBlendState,
970 const vector<DrawBufferInfo>& drawBuffers,
971 const glu::Framebuffer& framebuffer,
972 vector<TextureLevel>& refRenderbuffers)
973 {
974 const glw::Functions& gl = renderContext.getFunctions();
975 const glu::ShaderProgram program (gl, genShaderSources(preCommonBlendState, postCommonBlendState, drawBuffers));
976 const IVec2 size = drawBuffers[0].getSize();
977 const bool requiresBlendBarriers = requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers);
978
979 vector<deUint32> bufs;
980
981 bufs.resize(drawBuffers.size());
982
983 for (int bufNdx = 0; bufNdx < (int)bufs.size(); bufNdx++)
984 bufs[bufNdx] = (drawBuffers[bufNdx].getRender() ? GL_COLOR_ATTACHMENT0 + bufNdx : GL_NONE);
985
986 log << program;
987
988 gl.viewport(0, 0, size.x(), size.y());
989 gl.useProgram(program.getProgram());
990 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
991
992 setCommonBlendState(gl, preCommonBlendState);
993
994 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
995 setIndexedBlendState(gl, drawBuffers[renderbufferNdx].getBlendState(), renderbufferNdx);
996
997 setCommonBlendState(gl, postCommonBlendState);
998
999 gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
1000
1001 if (requiresBlendBarriers)
1002 gl.blendBarrierKHR();
1003
1004 renderGLQuad(renderContext, program);
1005
1006 if (requiresBlendBarriers)
1007 gl.blendBarrierKHR();
1008
1009 gl.drawBuffers(0, 0);
1010 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1011 gl.useProgram(0);
1012
1013 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
1014
1015 renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, refRenderbuffers);
1016 }
1017
logBlendState(TestLog & log,const BlendState & blend)1018 void logBlendState (TestLog& log,
1019 const BlendState& blend)
1020 {
1021 if (blend.enableBlend)
1022 {
1023 if (*blend.enableBlend)
1024 log << TestLog::Message << "Enable blending." << TestLog::EndMessage;
1025 else
1026 log << TestLog::Message << "Disable blending." << TestLog::EndMessage;
1027 }
1028
1029 if (blend.colorMask)
1030 {
1031 const BVec4 mask = *blend.colorMask;
1032
1033 log << TestLog::Message << "Set color mask: " << mask << "." << TestLog::EndMessage;
1034 }
1035
1036
1037 if (blend.blendEq)
1038 {
1039 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
1040
1041 if (blendEq.is<BlendEq>())
1042 log << TestLog::Message << "Set blend equation: " << glu::getBlendEquationStr(blendEq.get<BlendEq>()) << "." << TestLog::EndMessage;
1043 else if (blendEq.is<SeparateBlendEq>())
1044 log << TestLog::Message << "Set blend equation rgb: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().rgb) << ", alpha: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().alpha) << "." << TestLog::EndMessage;
1045 else
1046 DE_ASSERT(false);
1047 }
1048
1049 if (blend.blendFunc)
1050 {
1051 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
1052
1053 if (blendFunc.is<BlendFunc>())
1054 log << TestLog::Message << "Set blend function source: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().dst) << "." << TestLog::EndMessage;
1055 else if (blendFunc.is<SeparateBlendFunc>())
1056 {
1057 log << TestLog::Message << "Set blend function rgb source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.dst) << "." << TestLog::EndMessage;
1058 log << TestLog::Message << "Set blend function alpha source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.dst) << "." << TestLog::EndMessage;
1059 }
1060 else
1061 DE_ASSERT(false);
1062 }
1063 }
1064
logTestCaseInfo(TestLog & log,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)1065 void logTestCaseInfo (TestLog& log,
1066 const BlendState& preCommonBlendState,
1067 const BlendState& postCommonBlendState,
1068 const vector<DrawBufferInfo>& drawBuffers)
1069 {
1070 {
1071 tcu::ScopedLogSection drawBuffersSection(log, "DrawBuffers", "Draw buffers");
1072
1073 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
1074 {
1075 const tcu::ScopedLogSection drawBufferSection (log, "DrawBuffer" + de::toString(drawBufferNdx), "Draw Buffer " + de::toString(drawBufferNdx));
1076 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
1077
1078 log << TestLog::Message << "Format: " << drawBuffer.getFormat() << TestLog::EndMessage;
1079 log << TestLog::Message << "Size: " << drawBuffer.getSize() << TestLog::EndMessage;
1080 log << TestLog::Message << "Render: " << (drawBuffer.getRender() ? "true" : "false") << TestLog::EndMessage;
1081 }
1082 }
1083
1084 if (!preCommonBlendState.isEmpty())
1085 {
1086 tcu::ScopedLogSection s(log, "PreCommonState", "First set common blend state");
1087 logBlendState(log, preCommonBlendState);
1088 }
1089
1090 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
1091 {
1092 if (!drawBuffers[drawBufferNdx].getBlendState().isEmpty())
1093 {
1094 const tcu::ScopedLogSection s(log, "DrawBufferState" + de::toString(drawBufferNdx), "Set DrawBuffer " + de::toString(drawBufferNdx) + " state to");
1095
1096 logBlendState(log, drawBuffers[drawBufferNdx].getBlendState());
1097 }
1098 }
1099
1100 if (!postCommonBlendState.isEmpty())
1101 {
1102 tcu::ScopedLogSection s(log, "PostCommonState", "After set common blend state");
1103 logBlendState(log, postCommonBlendState);
1104 }
1105 }
1106
runTest(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)1107 void runTest (TestLog& log,
1108 tcu::ResultCollector& results,
1109 glu::RenderContext& renderContext,
1110
1111 const BlendState& preCommonBlendState,
1112 const BlendState& postCommonBlendState,
1113 const vector<DrawBufferInfo>& drawBuffers)
1114 {
1115 const glw::Functions& gl = renderContext.getFunctions();
1116 glu::RenderbufferVector renderbuffers (gl, drawBuffers.size());
1117 glu::Framebuffer framebuffer (gl);
1118 vector<TextureLevel> refRenderbuffers (drawBuffers.size());
1119
1120 logTestCaseInfo(log, preCommonBlendState, postCommonBlendState, drawBuffers);
1121
1122 genRenderbuffers(gl, drawBuffers, framebuffer, renderbuffers, refRenderbuffers);
1123
1124 renderQuad(log, renderContext, preCommonBlendState, postCommonBlendState, drawBuffers, framebuffer, refRenderbuffers);
1125
1126 verifyRenderbuffers(log, results, renderContext, renderbuffers, framebuffer, refRenderbuffers);
1127 }
1128
1129 class DrawBuffersIndexedTest : public TestCase
1130 {
1131 public:
1132 DrawBuffersIndexedTest (Context& context,
1133 const BlendState& preCommonBlendState,
1134 const BlendState& postCommonBlendState,
1135 const vector<DrawBufferInfo>& drawBuffers,
1136 const string& name,
1137 const string& description);
1138
1139 void init (void);
1140 IterateResult iterate (void);
1141
1142 private:
1143 const BlendState m_preCommonBlendState;
1144 const BlendState m_postCommonBlendState;
1145 const vector<DrawBufferInfo> m_drawBuffers;
1146 };
1147
DrawBuffersIndexedTest(Context & context,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const string & name,const string & description)1148 DrawBuffersIndexedTest::DrawBuffersIndexedTest (Context& context,
1149 const BlendState& preCommonBlendState,
1150 const BlendState& postCommonBlendState,
1151 const vector<DrawBufferInfo>& drawBuffers,
1152 const string& name,
1153 const string& description)
1154 : TestCase (context, name.c_str(), description.c_str())
1155 , m_preCommonBlendState (preCommonBlendState)
1156 , m_postCommonBlendState (postCommonBlendState)
1157 , m_drawBuffers (drawBuffers)
1158 {
1159 }
1160
init(void)1161 void DrawBuffersIndexedTest::init (void)
1162 {
1163 if (requiresAdvancedBlendEq(m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers) && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
1164 throw tcu::NotSupportedError("Extension GL_KHR_blend_equation_advanced not supported", "", __FILE__, __LINE__);
1165
1166 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1167 throw tcu::NotSupportedError("Extension GL_EXT_draw_buffers_indexed not supported", "", __FILE__, __LINE__);
1168 }
1169
iterate(void)1170 TestCase::IterateResult DrawBuffersIndexedTest::iterate (void)
1171 {
1172 TestLog& log = m_testCtx.getLog();
1173 tcu::ResultCollector results (log);
1174
1175 runTest(log, results, m_context.getRenderContext(), m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers);
1176
1177 results.setTestContextResult(m_testCtx);
1178
1179 return STOP;
1180 }
1181
getRandomBlendEq(de::Random & rng)1182 BlendEq getRandomBlendEq (de::Random& rng)
1183 {
1184 const BlendEq eqs[] =
1185 {
1186 GL_FUNC_ADD,
1187 GL_FUNC_SUBTRACT,
1188 GL_FUNC_REVERSE_SUBTRACT,
1189 GL_MIN,
1190 GL_MAX
1191 };
1192
1193 return de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(eqs)>(eqs, rng.getUint32() % DE_LENGTH_OF_ARRAY(eqs));
1194 }
1195
getRandomBlendFunc(de::Random & rng)1196 BlendFunc getRandomBlendFunc (de::Random& rng)
1197 {
1198 const deUint32 funcs[] =
1199 {
1200 GL_ZERO,
1201 GL_ONE,
1202 GL_SRC_COLOR,
1203 GL_ONE_MINUS_SRC_COLOR,
1204 GL_DST_COLOR,
1205 GL_ONE_MINUS_DST_COLOR,
1206 GL_SRC_ALPHA,
1207 GL_ONE_MINUS_SRC_ALPHA,
1208 GL_DST_ALPHA,
1209 GL_ONE_MINUS_DST_ALPHA,
1210 GL_CONSTANT_COLOR,
1211 GL_ONE_MINUS_CONSTANT_COLOR,
1212 GL_CONSTANT_ALPHA,
1213 GL_ONE_MINUS_CONSTANT_ALPHA,
1214 GL_SRC_ALPHA_SATURATE
1215 };
1216
1217 const deUint32 src = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
1218 const deUint32 dst = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
1219
1220 return BlendFunc(src, dst);
1221 }
1222
genRandomBlendState(de::Random & rng,BlendState & blendState)1223 void genRandomBlendState (de::Random& rng, BlendState& blendState)
1224 {
1225 if (rng.getBool())
1226 blendState.enableBlend = rng.getBool();
1227
1228 if (rng.getBool())
1229 {
1230 if (rng.getBool())
1231 blendState.blendEq = getRandomBlendEq(rng);
1232 else
1233 {
1234 const BlendEq rgb = getRandomBlendEq(rng);
1235 const BlendEq alpha = getRandomBlendEq(rng);
1236
1237 blendState.blendEq = SeparateBlendEq(rgb, alpha);
1238 }
1239 }
1240
1241 if (rng.getBool())
1242 {
1243 if (rng.getBool())
1244 blendState.blendFunc = getRandomBlendFunc(rng);
1245 else
1246 {
1247 const BlendFunc rgb = getRandomBlendFunc(rng);
1248 const BlendFunc alpha = getRandomBlendFunc(rng);
1249
1250 blendState.blendFunc = SeparateBlendFunc(rgb, alpha);
1251 }
1252 }
1253
1254 if (rng.getBool())
1255 {
1256 const bool red = rng.getBool();
1257 const bool green = rng.getBool();
1258 const bool blue = rng.getBool();
1259 const bool alpha = rng.getBool();
1260
1261 blendState.colorMask = BVec4(red, blue, green, alpha);
1262 }
1263 }
1264
getRandomFormat(de::Random & rng)1265 TextureFormat getRandomFormat (de::Random& rng)
1266 {
1267 const deUint32 glFormats[] =
1268 {
1269 GL_R8,
1270 GL_RG8,
1271 GL_RGB8,
1272 GL_RGB565,
1273 GL_RGBA4,
1274 GL_RGB5_A1,
1275 GL_RGBA8,
1276 GL_RGB10_A2,
1277 GL_RGB10_A2UI,
1278 GL_R8I,
1279 GL_R8UI,
1280 GL_R16I,
1281 GL_R16UI,
1282 GL_R32I,
1283 GL_R32UI,
1284 GL_RG8I,
1285 GL_RG8UI,
1286 GL_RG16I,
1287 GL_RG16UI,
1288 GL_RG32I,
1289 GL_RG32UI,
1290 GL_RGBA8I,
1291 GL_RGBA8UI,
1292 GL_RGBA16I,
1293 GL_RGBA16UI,
1294 GL_RGBA32I,
1295 GL_RGBA32UI
1296 };
1297
1298 return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % DE_LENGTH_OF_ARRAY(glFormats)));
1299 }
1300
genRandomTest(de::Random & rng,BlendState & preCommon,BlendState & postCommon,vector<DrawBufferInfo> & drawBuffers,int maxDrawBufferCount)1301 void genRandomTest (de::Random& rng, BlendState& preCommon, BlendState& postCommon, vector<DrawBufferInfo>& drawBuffers, int maxDrawBufferCount)
1302 {
1303 genRandomBlendState(rng, preCommon);
1304 genRandomBlendState(rng, postCommon);
1305
1306 for (int drawBufferNdx = 0; drawBufferNdx < maxDrawBufferCount; drawBufferNdx++)
1307 {
1308 const bool render = rng.getFloat() > 0.1f;
1309 const IVec2 size (64, 64);
1310 const TextureFormat format (getRandomFormat(rng));
1311 BlendState blendState;
1312
1313 genRandomBlendState(rng, blendState);
1314 drawBuffers.push_back(DrawBufferInfo(render, size, blendState, format));
1315 }
1316 }
1317
1318 class MaxDrawBuffersIndexedTest : public TestCase
1319 {
1320 public:
1321 MaxDrawBuffersIndexedTest (Context& contet, int seed);
1322
1323 void init (void);
1324 IterateResult iterate (void);
1325
1326 private:
1327 const int m_seed;
1328 };
1329
MaxDrawBuffersIndexedTest(Context & context,int seed)1330 MaxDrawBuffersIndexedTest::MaxDrawBuffersIndexedTest (Context& context, int seed)
1331 : TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str())
1332 , m_seed (deInt32Hash(seed) ^ 1558001307u)
1333 {
1334 }
1335
init(void)1336 void MaxDrawBuffersIndexedTest::init (void)
1337 {
1338 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1339 throw tcu::NotSupportedError("Extension GL_EXT_draw_buffers_indexed not supported", "", __FILE__, __LINE__);
1340 }
1341
iterate(void)1342 TestCase::IterateResult MaxDrawBuffersIndexedTest::iterate (void)
1343 {
1344 TestLog& log = m_testCtx.getLog();
1345 tcu::ResultCollector results (log);
1346 de::Random rng (m_seed);
1347 BlendState preCommonBlendState;
1348 BlendState postCommonBlendState;
1349 vector<DrawBufferInfo> drawBuffers;
1350
1351 genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, 4);
1352
1353 runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
1354
1355 results.setTestContextResult(m_testCtx);
1356
1357 return STOP;
1358 }
1359
1360 class ImplMaxDrawBuffersIndexedTest : public TestCase
1361 {
1362 public:
1363 ImplMaxDrawBuffersIndexedTest (Context& contet, int seed);
1364
1365 void init (void);
1366 IterateResult iterate (void);
1367
1368 private:
1369 const int m_seed;
1370 };
1371
ImplMaxDrawBuffersIndexedTest(Context & context,int seed)1372 ImplMaxDrawBuffersIndexedTest::ImplMaxDrawBuffersIndexedTest (Context& context, int seed)
1373 : TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str())
1374 , m_seed (deInt32Hash(seed) ^ 2686315738u)
1375 {
1376 }
1377
init(void)1378 void ImplMaxDrawBuffersIndexedTest::init (void)
1379 {
1380 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1381 throw tcu::NotSupportedError("Extension GL_EXT_draw_buffers_indexed not supported", "", __FILE__, __LINE__);
1382 }
1383
iterate(void)1384 TestCase::IterateResult ImplMaxDrawBuffersIndexedTest::iterate (void)
1385 {
1386 TestLog& log = m_testCtx.getLog();
1387 tcu::ResultCollector results (log);
1388 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1389 de::Random rng (m_seed);
1390 deInt32 maxDrawBuffers = 0;
1391 BlendState preCommonBlendState;
1392 BlendState postCommonBlendState;
1393 vector<DrawBufferInfo> drawBuffers;
1394
1395 gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1396 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_DRAW_BUFFERS) failed");
1397
1398 TCU_CHECK(maxDrawBuffers > 0);
1399
1400 genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, maxDrawBuffers);
1401
1402 runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
1403
1404 results.setTestContextResult(m_testCtx);
1405
1406 return STOP;
1407 }
1408
1409 enum PrePost
1410 {
1411 PRE,
1412 POST
1413 };
1414
createDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)1415 TestCase* createDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
1416 {
1417 const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
1418
1419 if (prepost == PRE)
1420 {
1421 const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
1422 commonState.blendEq,
1423 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
1424 tcu::nothing<BVec4>());
1425 vector<DrawBufferInfo> drawBuffers;
1426
1427 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1428 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1429
1430 return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
1431 }
1432 else if (prepost == POST)
1433 {
1434 const BlendState preState = BlendState(just(true),
1435 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
1436 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
1437 tcu::nothing<BVec4>());
1438 vector<DrawBufferInfo> drawBuffers;
1439
1440 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1441 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1442
1443 return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
1444 }
1445 else
1446 {
1447 DE_ASSERT(false);
1448 return DE_NULL;
1449 }
1450 }
1451
createAdvancedEqDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)1452 TestCase* createAdvancedEqDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
1453 {
1454 const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
1455
1456 if (prepost == PRE)
1457 {
1458 const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
1459 commonState.blendEq,
1460 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
1461 tcu::nothing<BVec4>());
1462 vector<DrawBufferInfo> drawBuffers;
1463
1464 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1465
1466 return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
1467 }
1468 else if (prepost == POST)
1469 {
1470 const BlendState preState = BlendState(just(true),
1471 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
1472 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
1473 tcu::nothing<BVec4>());
1474 vector<DrawBufferInfo> drawBuffers;
1475
1476 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1477
1478 return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
1479 }
1480 else
1481 {
1482 DE_ASSERT(false);
1483 return DE_NULL;
1484 }
1485 }
1486
addDrawBufferCommonTests(TestCaseGroup * root,PrePost prepost)1487 void addDrawBufferCommonTests (TestCaseGroup* root, PrePost prepost)
1488 {
1489 const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1490
1491 {
1492 const BlendState disableState = BlendState(just(false), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1493 const BlendState enableState = BlendState(just(true), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1494
1495 root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_enable", enableState, enableState));
1496 root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_disable", disableState, disableState));
1497 root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_enable", disableState, enableState));
1498 root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_disable", enableState, disableState));
1499 }
1500
1501 {
1502 const BlendState eqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1503 const BlendState eqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1504
1505 const BlendState separateEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_ADD, GL_FUNC_SUBTRACT)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1506 const BlendState separateEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_SUBTRACT, GL_FUNC_ADD)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1507
1508 const BlendState advancedEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE_KHR), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1509 const BlendState advancedEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_SCREEN_KHR), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1510
1511 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_blend_eq", eqStateA, eqStateB));
1512 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_separate_blend_eq", eqStateA, separateEqStateB));
1513 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_advanced_blend_eq", eqStateA, advancedEqStateB));
1514
1515 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_blend_eq", separateEqStateA, eqStateB));
1516 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_separate_blend_eq", separateEqStateA, separateEqStateB));
1517 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_advanced_blend_eq", separateEqStateA, advancedEqStateB));
1518
1519 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_blend_eq", advancedEqStateA, eqStateB));
1520 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_separate_blend_eq", advancedEqStateA, separateEqStateB));
1521 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_advanced_blend_eq", advancedEqStateA, advancedEqStateB));
1522 }
1523
1524 {
1525 const BlendState funcStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>());
1526 const BlendState funcStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>());
1527 const BlendState separateFuncStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA), BlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA))), Maybe<BVec4>());
1528 const BlendState separateFuncStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA), BlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA))), Maybe<BVec4>());
1529
1530 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_blend_func", funcStateA, funcStateB));
1531 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_separate_blend_func", funcStateA, separateFuncStateB));
1532 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_blend_func", separateFuncStateA, funcStateB));
1533 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_separate_blend_func", separateFuncStateA, separateFuncStateB));
1534 }
1535
1536 {
1537 const BlendState commonColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false)));
1538 const BlendState bufferColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(false, true, false, true)));
1539
1540 root->addChild(createDiffTest(root->getContext(), prepost, "common_color_mask_buffer_color_mask", commonColorMaskState, bufferColorMaskState));
1541 }
1542 }
1543
addRandomMaxTest(TestCaseGroup * root)1544 void addRandomMaxTest (TestCaseGroup* root)
1545 {
1546 for (int i = 0; i < 20; i++)
1547 root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
1548 }
1549
addRandomImplMaxTest(TestCaseGroup * root)1550 void addRandomImplMaxTest (TestCaseGroup* root)
1551 {
1552 for (int i = 0; i < 20; i++)
1553 root->addChild(new ImplMaxDrawBuffersIndexedTest(root->getContext(), i));
1554 }
1555
1556 } // anonymous
1557
createDrawBuffersIndexedTests(Context & context)1558 TestCaseGroup* createDrawBuffersIndexedTests (Context& context)
1559 {
1560 const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1561 TestCaseGroup* const group = new TestCaseGroup(context, "draw_buffers_indexed", "Test for indexed draw buffers. GL_EXT_draw_buffers_indexed.");
1562
1563 TestCaseGroup* const preGroup = new TestCaseGroup(context, "overwrite_common", "Set common state and overwrite it with draw buffer blend state.");
1564 TestCaseGroup* const postGroup = new TestCaseGroup(context, "overwrite_indexed", "Set indexed blend state and overwrite it ith common state.");
1565 TestCaseGroup* const randomGroup = new TestCaseGroup(context, "random", "Random indexed blend state tests.");
1566 TestCaseGroup* const maxGroup = new TestCaseGroup(context, "max_required_draw_buffers", "Random tests using minimum maximum number of draw buffers.");
1567 TestCaseGroup* const maxImplGroup = new TestCaseGroup(context, "max_implementation_draw_buffers", "Random tests using maximum number of draw buffers reported by implementation.");
1568
1569 group->addChild(preGroup);
1570 group->addChild(postGroup);
1571 group->addChild(randomGroup);
1572
1573 randomGroup->addChild(maxGroup);
1574 randomGroup->addChild(maxImplGroup);
1575
1576 addDrawBufferCommonTests(preGroup, PRE);
1577 addDrawBufferCommonTests(postGroup, POST);
1578 addRandomMaxTest(maxGroup);
1579 addRandomImplMaxTest(maxImplGroup);
1580
1581 return group;
1582 }
1583
1584 } // Functional
1585 } // gles31
1586 } // deqp
1587