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