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