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
isAdvancedBlendEq(BlendEq eq)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 {
SeparateBlendEqdeqp::gles31::Functional::__anon169a63d40111::SeparateBlendEq123 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 {
BlendFuncdeqp::gles31::Functional::__anon169a63d40111::BlendFunc135 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 {
SeparateBlendFuncdeqp::gles31::Functional::__anon169a63d40111::SeparateBlendFunc147 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 {
BlendStatedeqp::gles31::Functional::__anon169a63d40111::BlendState161 BlendState (void) {}
162
BlendStatedeqp::gles31::Functional::__anon169a63d40111::BlendState163 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
isEmptydeqp::gles31::Functional::__anon169a63d40111::BlendState174 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
setCommonBlendState(const glw::Functions & gl,const BlendState & blend)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
setIndexedBlendState(const glw::Functions & gl,const BlendState & blend,deUint32 index)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
getFormat(void) const281 const TextureFormat& getFormat (void) const { return m_format; }
getSize(void) const282 const IVec2& getSize (void) const { return m_size; }
getBlendState(void) const283 const BlendState& getBlendState (void) const { return m_blendState; }
getRender(void) const284 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
DrawBufferInfo(bool render,const IVec2 & size,const BlendState & blendState,const TextureFormat & format)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
clearRenderbuffer(const glw::Functions & gl,const tcu::TextureFormat & format,int renderbufferNdx,int renderbufferCount,tcu::TextureLevel & refRenderbuffer)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
genRenderbuffers(const glw::Functions & gl,const vector<DrawBufferInfo> & drawBuffers,const glu::Framebuffer & framebuffer,const glu::RenderbufferVector & renderbuffers,vector<TextureLevel> & refRenderbuffers)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
getFixedPointFormatThreshold(const tcu::TextureFormat & sourceFormat,const tcu::TextureFormat & readPixelsFormat)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
getFloatULPThreshold(const tcu::TextureFormat & sourceFormat,const tcu::TextureFormat & readPixelsFormat)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
verifyRenderbuffer(TestLog & log,tcu::ResultCollector & results,const tcu::TextureFormat & format,int renderbufferNdx,const tcu::TextureLevel & refRenderbuffer,const tcu::TextureLevel & result)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
getReadPixelFormat(const TextureFormat & format)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
verifyRenderbuffers(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const glu::RenderbufferVector & renderbuffers,const glu::Framebuffer & framebuffer,const vector<TextureLevel> & refRenderbuffers)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
setBlendState(rr::FragmentOperationState & fragOps,const BlendState & state)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
createRenderState(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const DrawBufferInfo & info)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
VertexShader(void)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
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const686 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
FragmentShader(int drawBufferNdx,const DrawBufferInfo & info)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
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const736 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
createVertexAttrib(const float * coords)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
renderRefQuad(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,vector<TextureLevel> & refRenderbuffers)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
requiresAdvancedBlendEq(const BlendState & pre,const BlendState post,const vector<DrawBufferInfo> & drawBuffers)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
genVertexSource(glu::RenderContext & renderContext)860 glu::VertexSource genVertexSource (glu::RenderContext& renderContext)
861 {
862 const bool isES32 = 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"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
876
877 return glu::VertexSource(tcu::StringTemplate(vertexSource).specialize(args));
878 }
879
genFragmentSource(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,glu::RenderContext & renderContext)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 isES32 = 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"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
976 args["GLSL_EXTENSION"] = isES32 ? "\n" : "#extension GL_KHR_blend_equation_advanced : require\n";
977
978 return glu::FragmentSource(tcu::StringTemplate(stream.str()).specialize(args));
979 }
980
genShaderSources(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,glu::RenderContext & renderContext)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
renderGLQuad(glu::RenderContext & renderContext,const glu::ShaderProgram & program)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
renderQuad(TestLog & log,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const glu::Framebuffer & framebuffer,vector<TextureLevel> & refRenderbuffers)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
logBlendState(TestLog & log,const BlendState & blend)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
logTestCaseInfo(TestLog & log,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)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
runTest(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)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
DrawBuffersIndexedTest(Context & context,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const string & name,const string & description)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
init(void)1191 void DrawBuffersIndexedTest::init (void)
1192 {
1193 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1194
1195 if (!isES32)
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
iterate(void)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
getRandomBlendEq(de::Random & rng)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
getRandomBlendFunc(de::Random & rng)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
genRandomBlendState(de::Random & rng,BlendState & blendState)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
getRandomFormat(de::Random & rng,Context & context)1300 TextureFormat getRandomFormat (de::Random& rng, Context& context)
1301 {
1302 const bool isES32 = 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 (isES32)
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
genRandomTest(de::Random & rng,BlendState & preCommon,BlendState & postCommon,vector<DrawBufferInfo> & drawBuffers,int maxDrawBufferCount,Context & context)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
MaxDrawBuffersIndexedTest(Context & context,int seed)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
init(void)1410 void MaxDrawBuffersIndexedTest::init (void)
1411 {
1412 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1413
1414 if (!isES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1415 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1416 }
1417
iterate(void)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
ImplMaxDrawBuffersIndexedTest(Context & context,int seed)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
init(void)1454 void ImplMaxDrawBuffersIndexedTest::init (void)
1455 {
1456 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1457
1458 if (!isES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1459 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1460 }
1461
iterate(void)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
createDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)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
createAdvancedEqDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)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
addDrawBufferCommonTests(TestCaseGroup * root,PrePost prepost)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
addRandomMaxTest(TestCaseGroup * root)1622 void addRandomMaxTest (TestCaseGroup* root)
1623 {
1624 for (int i = 0; i < 20; i++)
1625 root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
1626 }
1627
addRandomImplMaxTest(TestCaseGroup * root)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
createDrawBuffersIndexedTests(Context & context)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
1665