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