1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Indexed blend operation tests (GL_EXT_draw_buffers_indexed)
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fDrawBuffersIndexedTests.hpp"
25
26 #include "gluContextInfo.hpp"
27 #include "gluDrawUtil.hpp"
28 #include "gluObjectWrapper.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "gluShaderProgram.hpp"
31 #include "gluStrUtil.hpp"
32 #include "gluTextureUtil.hpp"
33
34 #include "sglrReferenceUtils.hpp"
35
36 #include "rrMultisamplePixelBufferAccess.hpp"
37 #include "rrRenderer.hpp"
38
39 #include "glwEnums.hpp"
40 #include "glwFunctions.hpp"
41
42 #include "tcuEither.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "tcuMaybe.hpp"
45 #include "tcuResultCollector.hpp"
46 #include "tcuStringTemplate.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuTexture.hpp"
49 #include "tcuTextureUtil.hpp"
50 #include "tcuVector.hpp"
51 #include "tcuVectorUtil.hpp"
52 #include "tcuFloat.hpp"
53
54 #include "deRandom.hpp"
55 #include "deArrayUtil.hpp"
56 #include "deStringUtil.hpp"
57 #include "deUniquePtr.hpp"
58
59 #include "deInt32.h"
60
61 #include <string>
62 #include <vector>
63 #include <map>
64
65 using tcu::BVec4;
66 using tcu::Either;
67 using tcu::IVec2;
68 using tcu::IVec4;
69 using tcu::Maybe;
70 using tcu::TestLog;
71 using tcu::TextureFormat;
72 using tcu::TextureLevel;
73 using tcu::UVec4;
74 using tcu::Vec2;
75 using tcu::Vec4;
76 using tcu::just;
77
78 using std::string;
79 using std::vector;
80 using std::map;
81
82 using sglr::rr_util::mapGLBlendEquation;
83 using sglr::rr_util::mapGLBlendFunc;
84 using sglr::rr_util::mapGLBlendEquationAdvanced;
85
86 namespace deqp
87 {
88 namespace gles31
89 {
90 namespace Functional
91 {
92 namespace
93 {
94
95 typedef deUint32 BlendEq;
96
isAdvancedBlendEq(BlendEq eq)97 bool isAdvancedBlendEq (BlendEq eq)
98 {
99 switch (eq)
100 {
101 case GL_MULTIPLY: return true;
102 case GL_SCREEN: return true;
103 case GL_OVERLAY: return true;
104 case GL_DARKEN: return true;
105 case GL_LIGHTEN: return true;
106 case GL_COLORDODGE: return true;
107 case GL_COLORBURN: return true;
108 case GL_HARDLIGHT: return true;
109 case GL_SOFTLIGHT: return true;
110 case GL_DIFFERENCE: return true;
111 case GL_EXCLUSION: return true;
112 case GL_HSL_HUE: return true;
113 case GL_HSL_SATURATION: return true;
114 case GL_HSL_COLOR: return true;
115 case GL_HSL_LUMINOSITY: return true;
116 default:
117 return false;
118 }
119 }
120
121 struct SeparateBlendEq
122 {
SeparateBlendEqdeqp::gles31::Functional::__anon758847bb0111::SeparateBlendEq123 SeparateBlendEq (BlendEq rgb_, BlendEq alpha_)
124 : rgb (rgb_)
125 , alpha (alpha_)
126 {
127 }
128
129 BlendEq rgb;
130 BlendEq alpha;
131 };
132
133 struct BlendFunc
134 {
BlendFuncdeqp::gles31::Functional::__anon758847bb0111::BlendFunc135 BlendFunc (deUint32 src_, deUint32 dst_)
136 : src (src_)
137 , dst (dst_)
138 {
139 }
140
141 deUint32 src;
142 deUint32 dst;
143 };
144
145 struct SeparateBlendFunc
146 {
SeparateBlendFuncdeqp::gles31::Functional::__anon758847bb0111::SeparateBlendFunc147 SeparateBlendFunc (BlendFunc rgb_, BlendFunc alpha_)
148 : rgb (rgb_)
149 , alpha (alpha_)
150 {
151 }
152
153 BlendFunc rgb;
154 BlendFunc alpha;
155 };
156
157 typedef deUint32 DrawBuffer;
158
159 struct BlendState
160 {
BlendStatedeqp::gles31::Functional::__anon758847bb0111::BlendState161 BlendState (void) {}
162
BlendStatedeqp::gles31::Functional::__anon758847bb0111::BlendState163 BlendState (const Maybe<bool>& enableBlend_,
164 const Maybe<Either<BlendEq, SeparateBlendEq> >& blendEq_,
165 const Maybe<Either<BlendFunc, SeparateBlendFunc> >& blendFunc_,
166 const Maybe<BVec4>& colorMask_)
167 : enableBlend (enableBlend_)
168 , blendEq (blendEq_)
169 , blendFunc (blendFunc_)
170 , colorMask (colorMask_)
171 {
172 }
173
isEmptydeqp::gles31::Functional::__anon758847bb0111::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 return Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
457 }
458
getFloatULPThreshold(const tcu::TextureFormat & sourceFormat,const tcu::TextureFormat & readPixelsFormat)459 UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
460 {
461 const tcu::IVec4 srcMantissaBits = tcu::getTextureFormatMantissaBitDepth(sourceFormat);
462 const tcu::IVec4 readMantissaBits = tcu::getTextureFormatMantissaBitDepth(readPixelsFormat);
463 tcu::IVec4 ULPDiff(0);
464
465 for (int i = 0; i < 4; i++)
466 if (readMantissaBits[i] >= srcMantissaBits[i])
467 ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i];
468
469 return UVec4(4) * (UVec4(1) << (ULPDiff.cast<deUint32>()));
470 }
471
verifyRenderbuffer(TestLog & log,tcu::ResultCollector & results,const tcu::TextureFormat & format,int renderbufferNdx,const tcu::TextureLevel & refRenderbuffer,const tcu::TextureLevel & result)472 void verifyRenderbuffer (TestLog& log,
473 tcu::ResultCollector& results,
474 const tcu::TextureFormat& format,
475 int renderbufferNdx,
476 const tcu::TextureLevel& refRenderbuffer,
477 const tcu::TextureLevel& result)
478 {
479 switch (tcu::getTextureChannelClass(format.type))
480 {
481 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
482 {
483 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
484 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
485 const UVec4 threshold = getFloatULPThreshold(format, result.getFormat());
486
487 if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
488 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
489
490 break;
491 }
492
493 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
494 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
495 {
496 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
497 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
498 const UVec4 threshold (1, 1, 1, 1);
499
500 if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
501 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
502
503 break;
504 }
505
506 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
507 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
508 {
509 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
510 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
511 const Vec4 threshold = getFixedPointFormatThreshold(format, result.getFormat());
512
513 if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
514 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
515
516 break;
517 }
518
519 default:
520 DE_ASSERT(DE_FALSE);
521 }
522 }
523
getReadPixelFormat(const TextureFormat & format)524 TextureFormat getReadPixelFormat (const TextureFormat& format)
525 {
526 switch (tcu::getTextureChannelClass(format.type))
527 {
528 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
529 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32);
530
531 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
532 return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32);
533
534 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
535 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
536 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
537
538 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
539 return TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT);
540
541 default:
542 DE_ASSERT(false);
543 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
544 }
545 }
546
verifyRenderbuffers(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const glu::RenderbufferVector & renderbuffers,const glu::Framebuffer & framebuffer,const vector<TextureLevel> & refRenderbuffers)547 void verifyRenderbuffers (TestLog& log,
548 tcu::ResultCollector& results,
549 glu::RenderContext& renderContext,
550 const glu::RenderbufferVector& renderbuffers,
551 const glu::Framebuffer& framebuffer,
552 const vector<TextureLevel>& refRenderbuffers)
553 {
554 const glw::Functions& gl = renderContext.getFunctions();
555
556 DE_ASSERT(renderbuffers.size() == refRenderbuffers.size());
557
558 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
559
560 for (int renderbufferNdx = 0; renderbufferNdx < (int)renderbuffers.size(); renderbufferNdx++)
561 {
562 const TextureLevel& refRenderbuffer = refRenderbuffers[renderbufferNdx];
563 const int width = refRenderbuffer.getWidth();
564 const int height = refRenderbuffer.getHeight();
565 const TextureFormat format = refRenderbuffer.getFormat();
566
567 tcu::TextureLevel result (getReadPixelFormat(format), width, height);
568
569 gl.readBuffer(GL_COLOR_ATTACHMENT0 + renderbufferNdx);
570 glu::readPixels(renderContext, 0, 0, result.getAccess());
571 GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels from renderbuffer failed.");
572
573 verifyRenderbuffer(log, results, format, renderbufferNdx, refRenderbuffer, result);
574 }
575
576 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
577 }
578
579 static const float s_quadCoords[] =
580 {
581 -0.5f, -0.5f,
582 0.5f, -0.5f,
583 0.5f, 0.5f,
584
585 0.5f, 0.5f,
586 -0.5f, 0.5f,
587 -0.5f, -0.5f
588 };
589
setBlendState(rr::FragmentOperationState & fragOps,const BlendState & state)590 void setBlendState (rr::FragmentOperationState& fragOps, const BlendState& state)
591 {
592 if (state.blendEq)
593 {
594 if (state.blendEq->is<BlendEq>())
595 {
596 if (isAdvancedBlendEq(state.blendEq->get<BlendEq>()))
597 {
598 const rr::BlendEquationAdvanced equation = mapGLBlendEquationAdvanced(state.blendEq->get<BlendEq>());
599
600 fragOps.blendMode = rr::BLENDMODE_ADVANCED;
601 fragOps.blendEquationAdvaced = equation;
602 }
603 else
604 {
605 const rr::BlendEquation equation = mapGLBlendEquation(state.blendEq->get<BlendEq>());
606
607 fragOps.blendMode = rr::BLENDMODE_STANDARD;
608 fragOps.blendRGBState.equation = equation;
609 fragOps.blendAState.equation = equation;
610 }
611 }
612 else
613 {
614 DE_ASSERT(state.blendEq->is<SeparateBlendEq>());
615
616 fragOps.blendMode = rr::BLENDMODE_STANDARD;
617 fragOps.blendRGBState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().rgb);
618 fragOps.blendAState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().alpha);
619 }
620 }
621
622 if (state.blendFunc)
623 {
624 if (state.blendFunc->is<BlendFunc>())
625 {
626 const rr::BlendFunc srcFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().src);
627 const rr::BlendFunc dstFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().dst);
628
629 fragOps.blendRGBState.srcFunc = srcFunction;
630 fragOps.blendRGBState.dstFunc = dstFunction;
631
632 fragOps.blendAState.srcFunc = srcFunction;
633 fragOps.blendAState.dstFunc = dstFunction;
634 }
635 else
636 {
637 DE_ASSERT(state.blendFunc->is<SeparateBlendFunc>());
638
639 fragOps.blendRGBState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.src);
640 fragOps.blendRGBState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.dst);
641
642 fragOps.blendAState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.src);
643 fragOps.blendAState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.dst);
644 }
645 }
646
647 if (state.colorMask)
648 fragOps.colorMask = *state.colorMask;
649 }
650
createRenderState(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const DrawBufferInfo & info,int subpixelBits)651 rr::RenderState createRenderState (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const DrawBufferInfo& info, int subpixelBits)
652 {
653 const IVec2 size = info.getSize();
654 rr::RenderState state (rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y())), subpixelBits);
655
656 state.fragOps.blendMode = rr::BLENDMODE_STANDARD;
657
658 setBlendState(state.fragOps, preCommonBlendState);
659 setBlendState(state.fragOps, info.getBlendState());
660 setBlendState(state.fragOps, postCommonBlendState);
661
662 if (postCommonBlendState.enableBlend)
663 state.fragOps.blendMode = (*(postCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
664 else if (info.getBlendState().enableBlend)
665 state.fragOps.blendMode = (*(info.getBlendState().enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
666 else if (preCommonBlendState.enableBlend)
667 state.fragOps.blendMode = (*(preCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
668 else
669 state.fragOps.blendMode = rr::BLENDMODE_NONE;
670
671 if (tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
672 && tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
673 && tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
674 state.fragOps.blendMode = rr::BLENDMODE_NONE;
675
676 return state;
677 }
678
679 class VertexShader : public rr::VertexShader
680 {
681 public:
682 VertexShader (void);
683 virtual void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
684 };
685
VertexShader(void)686 VertexShader::VertexShader (void)
687 : rr::VertexShader (1, 1)
688 {
689 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
690 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
691 }
692
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const693 void VertexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
694 {
695 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
696 {
697 rr::VertexPacket& packet = *packets[packetNdx];
698
699 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
700 packet.outputs[0] = 0.5f * (Vec4(1.0f) + rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx));
701 }
702 }
703
704 class FragmentShader : public rr::FragmentShader
705 {
706 public:
707 FragmentShader (int drawBufferNdx, const DrawBufferInfo& info);
708 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
709
710 private:
711 const int m_drawBufferNdx;
712 const DrawBufferInfo m_info;
713 };
714
FragmentShader(int drawBufferNdx,const DrawBufferInfo & info)715 FragmentShader::FragmentShader (int drawBufferNdx, const DrawBufferInfo& info)
716 : rr::FragmentShader (1, 1)
717 , m_drawBufferNdx (drawBufferNdx)
718 , m_info (info)
719 {
720 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
721
722 switch (tcu::getTextureChannelClass(m_info.getFormat().type))
723 {
724 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
725 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
726 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
727 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
728 break;
729
730 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
731 m_outputs[0].type = rr::GENERICVECTYPE_UINT32;
732 break;
733
734 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
735 m_outputs[0].type = rr::GENERICVECTYPE_INT32;
736 break;
737
738 default:
739 DE_ASSERT(false);
740 };
741 }
742
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const743 void FragmentShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
744 {
745 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
746 {
747 rr::FragmentPacket& packet = packets[packetNdx];
748
749 DE_ASSERT(m_drawBufferNdx >= 0);
750 DE_UNREF(m_info);
751
752 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
753 {
754 const Vec2 vColor = rr::readVarying<float>(packet, context, 0, fragNdx).xy();
755 const float values[] =
756 {
757 vColor.x(),
758 vColor.y(),
759 (1.0f - vColor.x()),
760 (1.0f - vColor.y())
761 };
762
763 switch (tcu::getTextureChannelClass(m_info.getFormat().type))
764 {
765 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
766 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
767 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
768 {
769 const Vec4 color (values[(m_drawBufferNdx + 0) % 4],
770 values[(m_drawBufferNdx + 1) % 4],
771 values[(m_drawBufferNdx + 2) % 4],
772 values[(m_drawBufferNdx + 3) % 4]);
773
774 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
775 break;
776 }
777
778 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
779 {
780 const UVec4 color ((deUint32)(values[(m_drawBufferNdx + 0) % 4]),
781 (deUint32)(values[(m_drawBufferNdx + 1) % 4]),
782 (deUint32)(values[(m_drawBufferNdx + 2) % 4]),
783 (deUint32)(values[(m_drawBufferNdx + 3) % 4]));
784
785 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
786 break;
787 }
788
789 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
790 {
791 const IVec4 color ((deInt32)(values[(m_drawBufferNdx + 0) % 4]),
792 (deInt32)(values[(m_drawBufferNdx + 1) % 4]),
793 (deInt32)(values[(m_drawBufferNdx + 2) % 4]),
794 (deInt32)(values[(m_drawBufferNdx + 3) % 4]));
795
796 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
797 break;
798 }
799
800 default:
801 DE_ASSERT(DE_FALSE);
802 };
803 }
804 }
805 }
806
createVertexAttrib(const float * coords)807 rr::VertexAttrib createVertexAttrib (const float* coords)
808 {
809 rr::VertexAttrib attrib;
810
811 attrib.type = rr::VERTEXATTRIBTYPE_FLOAT;
812 attrib.size = 2;
813 attrib.pointer = coords;
814
815 return attrib;
816 }
817
renderRefQuad(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const int subpixelBits,vector<TextureLevel> & refRenderbuffers)818 void renderRefQuad (const BlendState& preCommonBlendState,
819 const BlendState& postCommonBlendState,
820 const vector<DrawBufferInfo>& drawBuffers,
821 const int subpixelBits,
822 vector<TextureLevel>& refRenderbuffers)
823 {
824 const rr::Renderer renderer;
825 const rr::PrimitiveList primitives (rr::PRIMITIVETYPE_TRIANGLES, 6, 0);
826 const rr::VertexAttrib vertexAttribs[] =
827 {
828 createVertexAttrib(s_quadCoords)
829 };
830
831 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
832 {
833 if (drawBuffers[drawBufferNdx].getRender())
834 {
835 const rr::RenderState renderState (createRenderState(preCommonBlendState, postCommonBlendState, drawBuffers[drawBufferNdx], subpixelBits));
836 const rr::RenderTarget renderTarget (rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refRenderbuffers[drawBufferNdx].getAccess()));
837 const VertexShader vertexShader;
838 const FragmentShader fragmentShader (drawBufferNdx, drawBuffers[drawBufferNdx]);
839 const rr::Program program (&vertexShader, &fragmentShader);
840 const rr::DrawCommand command (renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, primitives);
841
842 renderer.draw(command);
843 }
844 }
845 }
846
requiresAdvancedBlendEq(const BlendState & pre,const BlendState post,const vector<DrawBufferInfo> & drawBuffers)847 bool requiresAdvancedBlendEq (const BlendState& pre, const BlendState post, const vector<DrawBufferInfo>& drawBuffers)
848 {
849 bool requiresAdvancedBlendEq = false;
850
851 if (pre.blendEq && pre.blendEq->is<BlendEq>())
852 requiresAdvancedBlendEq |= isAdvancedBlendEq(pre.blendEq->get<BlendEq>());
853
854 if (post.blendEq && post.blendEq->is<BlendEq>())
855 requiresAdvancedBlendEq |= isAdvancedBlendEq(post.blendEq->get<BlendEq>());
856
857 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
858 {
859 const BlendState& drawBufferBlendState = drawBuffers[drawBufferNdx].getBlendState();
860
861 if (drawBufferBlendState.blendEq && drawBufferBlendState.blendEq->is<BlendEq>())
862 requiresAdvancedBlendEq |= isAdvancedBlendEq(drawBufferBlendState.blendEq->get<BlendEq>());
863 }
864
865 return requiresAdvancedBlendEq;
866 }
867
genVertexSource(glu::RenderContext & renderContext)868 glu::VertexSource genVertexSource (glu::RenderContext& renderContext)
869 {
870 const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
871
872 const char* const vertexSource =
873 "${GLSL_VERSION_DECL}\n"
874 "layout(location=0) in highp vec2 i_coord;\n"
875 "out highp vec2 v_color;\n"
876 "void main (void)\n"
877 "{\n"
878 "\tv_color = 0.5 * (vec2(1.0) + i_coord);\n"
879 "\tgl_Position = vec4(i_coord, 0.0, 1.0);\n"
880 "}";
881
882 map<string, string> args;
883 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
884
885 return glu::VertexSource(tcu::StringTemplate(vertexSource).specialize(args));
886 }
887
genFragmentSource(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,glu::RenderContext & renderContext)888 glu::FragmentSource genFragmentSource (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
889 {
890 std::ostringstream stream;
891 const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
892
893 stream << "${GLSL_VERSION_DECL}\n";
894
895 if (requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers))
896 {
897 stream << "${GLSL_EXTENSION}"
898 << "layout(blend_support_all_equations) out;\n";
899 }
900
901 stream << "in highp vec2 v_color;\n";
902
903 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
904 {
905 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
906 const TextureFormat& format = drawBuffer.getFormat();
907
908 stream << "layout(location=" << drawBufferNdx << ") out highp ";
909
910 switch (tcu::getTextureChannelClass(format.type))
911 {
912 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
913 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
914 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
915 stream << "vec4";
916 break;
917
918 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
919 stream << "uvec4";
920 break;
921
922 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
923 stream << "ivec4";
924 break;
925
926 default:
927 DE_ASSERT(DE_FALSE);
928 };
929
930 stream << " o_drawBuffer" << drawBufferNdx << ";\n";
931 }
932
933 stream << "void main (void)\n"
934 << "{\n";
935
936 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
937 {
938 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
939 const TextureFormat& format = drawBuffer.getFormat();
940 const char* const values[] =
941 {
942 "v_color.x",
943 "v_color.y",
944 "(1.0 - v_color.x)",
945 "(1.0 - v_color.y)"
946 };
947
948 stream << "\to_drawBuffer" << drawBufferNdx;
949
950 switch (tcu::getTextureChannelClass(format.type))
951 {
952 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
953 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
954 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
955 stream << " = vec4(" << values[(drawBufferNdx + 0) % 4]
956 << ", " << values[(drawBufferNdx + 1) % 4]
957 << ", " << values[(drawBufferNdx + 2) % 4]
958 << ", " << values[(drawBufferNdx + 3) % 4] << ");\n";
959 break;
960
961 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
962 stream << " = uvec4(uint(" << values[(drawBufferNdx + 0) % 4]
963 << "), uint(" << values[(drawBufferNdx + 1) % 4]
964 << "), uint(" << values[(drawBufferNdx + 2) % 4]
965 << "), uint(" << values[(drawBufferNdx + 3) % 4] << "));\n";
966 break;
967
968 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
969 stream << " = ivec4(int(" << values[(drawBufferNdx + 0) % 4]
970 << "), int(" << values[(drawBufferNdx + 1) % 4]
971 << "), int(" << values[(drawBufferNdx + 2) % 4]
972 << "), int(" << values[(drawBufferNdx + 3) % 4] << "));\n";
973 break;
974
975 default:
976 DE_ASSERT(DE_FALSE);
977 };
978 }
979
980 stream << "}";
981
982 map<string, string> args;
983 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
984 args["GLSL_EXTENSION"] = supportsES32 ? "\n" : "#extension GL_KHR_blend_equation_advanced : require\n";
985
986 return glu::FragmentSource(tcu::StringTemplate(stream.str()).specialize(args));
987 }
988
genShaderSources(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,glu::RenderContext & renderContext)989 glu::ProgramSources genShaderSources (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
990 {
991 return glu::ProgramSources() << genVertexSource(renderContext) << genFragmentSource(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext);
992 }
993
renderGLQuad(glu::RenderContext & renderContext,const glu::ShaderProgram & program)994 void renderGLQuad (glu::RenderContext& renderContext,
995 const glu::ShaderProgram& program)
996 {
997 const glu::VertexArrayBinding vertexArrays[] =
998 {
999 glu::VertexArrayBinding(glu::BindingPoint(0), glu::VertexArrayPointer(glu::VTX_COMP_FLOAT, glu::VTX_COMP_CONVERT_NONE, 2, 6, 0, s_quadCoords))
1000 };
1001
1002 glu::draw(renderContext, program.getProgram(), 1, vertexArrays, glu::pr::Triangles(6));
1003 }
1004
renderQuad(TestLog & log,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const glu::Framebuffer & framebuffer,vector<TextureLevel> & refRenderbuffers)1005 void renderQuad (TestLog& log,
1006 glu::RenderContext& renderContext,
1007 const BlendState& preCommonBlendState,
1008 const BlendState& postCommonBlendState,
1009 const vector<DrawBufferInfo>& drawBuffers,
1010 const glu::Framebuffer& framebuffer,
1011 vector<TextureLevel>& refRenderbuffers)
1012 {
1013 const glw::Functions& gl = renderContext.getFunctions();
1014 const glu::ShaderProgram program (gl, genShaderSources(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext));
1015 const IVec2 size = drawBuffers[0].getSize();
1016 const bool requiresBlendBarriers = requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers);
1017
1018 vector<deUint32> bufs;
1019
1020 bufs.resize(drawBuffers.size());
1021
1022 for (int bufNdx = 0; bufNdx < (int)bufs.size(); bufNdx++)
1023 bufs[bufNdx] = (drawBuffers[bufNdx].getRender() ? GL_COLOR_ATTACHMENT0 + bufNdx : GL_NONE);
1024
1025 log << program;
1026
1027 gl.viewport(0, 0, size.x(), size.y());
1028 gl.useProgram(program.getProgram());
1029 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
1030
1031 setCommonBlendState(gl, preCommonBlendState);
1032
1033 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
1034 setIndexedBlendState(gl, drawBuffers[renderbufferNdx].getBlendState(), renderbufferNdx);
1035
1036 setCommonBlendState(gl, postCommonBlendState);
1037
1038 gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
1039
1040 if (requiresBlendBarriers)
1041 gl.blendBarrier();
1042
1043 renderGLQuad(renderContext, program);
1044
1045 if (requiresBlendBarriers)
1046 gl.blendBarrier();
1047
1048 gl.drawBuffers(0, 0);
1049 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1050 gl.useProgram(0);
1051
1052 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
1053
1054 int subpixelBits = 0;
1055 gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
1056
1057 renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, subpixelBits, refRenderbuffers);
1058 }
1059
logBlendState(TestLog & log,const BlendState & blend)1060 void logBlendState (TestLog& log,
1061 const BlendState& blend)
1062 {
1063 if (blend.enableBlend)
1064 {
1065 if (*blend.enableBlend)
1066 log << TestLog::Message << "Enable blending." << TestLog::EndMessage;
1067 else
1068 log << TestLog::Message << "Disable blending." << TestLog::EndMessage;
1069 }
1070
1071 if (blend.colorMask)
1072 {
1073 const BVec4 mask = *blend.colorMask;
1074
1075 log << TestLog::Message << "Set color mask: " << mask << "." << TestLog::EndMessage;
1076 }
1077
1078 if (blend.blendEq)
1079 {
1080 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
1081
1082 if (blendEq.is<BlendEq>())
1083 log << TestLog::Message << "Set blend equation: " << glu::getBlendEquationStr(blendEq.get<BlendEq>()) << "." << TestLog::EndMessage;
1084 else if (blendEq.is<SeparateBlendEq>())
1085 log << TestLog::Message << "Set blend equation rgb: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().rgb) << ", alpha: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().alpha) << "." << TestLog::EndMessage;
1086 else
1087 DE_ASSERT(false);
1088 }
1089
1090 if (blend.blendFunc)
1091 {
1092 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
1093
1094 if (blendFunc.is<BlendFunc>())
1095 log << TestLog::Message << "Set blend function source: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().dst) << "." << TestLog::EndMessage;
1096 else if (blendFunc.is<SeparateBlendFunc>())
1097 {
1098 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;
1099 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;
1100 }
1101 else
1102 DE_ASSERT(false);
1103 }
1104 }
1105
logTestCaseInfo(TestLog & log,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)1106 void logTestCaseInfo (TestLog& log,
1107 const BlendState& preCommonBlendState,
1108 const BlendState& postCommonBlendState,
1109 const vector<DrawBufferInfo>& drawBuffers)
1110 {
1111 {
1112 tcu::ScopedLogSection drawBuffersSection(log, "DrawBuffers", "Draw buffers");
1113
1114 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
1115 {
1116 const tcu::ScopedLogSection drawBufferSection (log, "DrawBuffer" + de::toString(drawBufferNdx), "Draw Buffer " + de::toString(drawBufferNdx));
1117 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
1118
1119 log << TestLog::Message << "Format: " << drawBuffer.getFormat() << TestLog::EndMessage;
1120 log << TestLog::Message << "Size: " << drawBuffer.getSize() << TestLog::EndMessage;
1121 log << TestLog::Message << "Render: " << (drawBuffer.getRender() ? "true" : "false") << TestLog::EndMessage;
1122 }
1123 }
1124
1125 if (!preCommonBlendState.isEmpty())
1126 {
1127 tcu::ScopedLogSection s(log, "PreCommonState", "First set common blend state");
1128 logBlendState(log, preCommonBlendState);
1129 }
1130
1131 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
1132 {
1133 if (!drawBuffers[drawBufferNdx].getBlendState().isEmpty())
1134 {
1135 const tcu::ScopedLogSection s(log, "DrawBufferState" + de::toString(drawBufferNdx), "Set DrawBuffer " + de::toString(drawBufferNdx) + " state to");
1136
1137 logBlendState(log, drawBuffers[drawBufferNdx].getBlendState());
1138 }
1139 }
1140
1141 if (!postCommonBlendState.isEmpty())
1142 {
1143 tcu::ScopedLogSection s(log, "PostCommonState", "After set common blend state");
1144 logBlendState(log, postCommonBlendState);
1145 }
1146 }
1147
runTest(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)1148 void runTest (TestLog& log,
1149 tcu::ResultCollector& results,
1150 glu::RenderContext& renderContext,
1151
1152 const BlendState& preCommonBlendState,
1153 const BlendState& postCommonBlendState,
1154 const vector<DrawBufferInfo>& drawBuffers)
1155 {
1156 const glw::Functions& gl = renderContext.getFunctions();
1157 glu::RenderbufferVector renderbuffers (gl, drawBuffers.size());
1158 glu::Framebuffer framebuffer (gl);
1159 vector<TextureLevel> refRenderbuffers (drawBuffers.size());
1160
1161 logTestCaseInfo(log, preCommonBlendState, postCommonBlendState, drawBuffers);
1162
1163 genRenderbuffers(gl, drawBuffers, framebuffer, renderbuffers, refRenderbuffers);
1164
1165 renderQuad(log, renderContext, preCommonBlendState, postCommonBlendState, drawBuffers, framebuffer, refRenderbuffers);
1166
1167 verifyRenderbuffers(log, results, renderContext, renderbuffers, framebuffer, refRenderbuffers);
1168 }
1169
1170 class DrawBuffersIndexedTest : public TestCase
1171 {
1172 public:
1173 DrawBuffersIndexedTest (Context& context,
1174 const BlendState& preCommonBlendState,
1175 const BlendState& postCommonBlendState,
1176 const vector<DrawBufferInfo>& drawBuffers,
1177 const string& name,
1178 const string& description);
1179
1180 void init (void);
1181 IterateResult iterate (void);
1182
1183 private:
1184 const BlendState m_preCommonBlendState;
1185 const BlendState m_postCommonBlendState;
1186 const vector<DrawBufferInfo> m_drawBuffers;
1187 };
1188
DrawBuffersIndexedTest(Context & context,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const string & name,const string & description)1189 DrawBuffersIndexedTest::DrawBuffersIndexedTest (Context& context,
1190 const BlendState& preCommonBlendState,
1191 const BlendState& postCommonBlendState,
1192 const vector<DrawBufferInfo>& drawBuffers,
1193 const string& name,
1194 const string& description)
1195 : TestCase (context, name.c_str(), description.c_str())
1196 , m_preCommonBlendState (preCommonBlendState)
1197 , m_postCommonBlendState (postCommonBlendState)
1198 , m_drawBuffers (drawBuffers)
1199 {
1200 }
1201
init(void)1202 void DrawBuffersIndexedTest::init (void)
1203 {
1204 const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
1205
1206 if (!supportsES32orGL45)
1207 {
1208 if (requiresAdvancedBlendEq(m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers) && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
1209 TCU_THROW(NotSupportedError, "Extension GL_KHR_blend_equation_advanced not supported");
1210
1211 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1212 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1213 }
1214 }
1215
iterate(void)1216 TestCase::IterateResult DrawBuffersIndexedTest::iterate (void)
1217 {
1218 TestLog& log = m_testCtx.getLog();
1219 tcu::ResultCollector results (log);
1220
1221 runTest(log, results, m_context.getRenderContext(), m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers);
1222
1223 results.setTestContextResult(m_testCtx);
1224
1225 return STOP;
1226 }
1227
getRandomBlendEq(de::Random & rng)1228 BlendEq getRandomBlendEq (de::Random& rng)
1229 {
1230 const BlendEq eqs[] =
1231 {
1232 GL_FUNC_ADD,
1233 GL_FUNC_SUBTRACT,
1234 GL_FUNC_REVERSE_SUBTRACT,
1235 GL_MIN,
1236 GL_MAX
1237 };
1238
1239 return de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(eqs)>(eqs, rng.getUint32() % DE_LENGTH_OF_ARRAY(eqs));
1240 }
1241
getRandomBlendFunc(de::Random & rng)1242 BlendFunc getRandomBlendFunc (de::Random& rng)
1243 {
1244 const deUint32 funcs[] =
1245 {
1246 GL_ZERO,
1247 GL_ONE,
1248 GL_SRC_COLOR,
1249 GL_ONE_MINUS_SRC_COLOR,
1250 GL_DST_COLOR,
1251 GL_ONE_MINUS_DST_COLOR,
1252 GL_SRC_ALPHA,
1253 GL_ONE_MINUS_SRC_ALPHA,
1254 GL_DST_ALPHA,
1255 GL_ONE_MINUS_DST_ALPHA,
1256 GL_CONSTANT_COLOR,
1257 GL_ONE_MINUS_CONSTANT_COLOR,
1258 GL_CONSTANT_ALPHA,
1259 GL_ONE_MINUS_CONSTANT_ALPHA,
1260 GL_SRC_ALPHA_SATURATE
1261 };
1262
1263 const deUint32 src = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
1264 const deUint32 dst = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
1265
1266 return BlendFunc(src, dst);
1267 }
1268
genRandomBlendState(de::Random & rng,BlendState & blendState)1269 void genRandomBlendState (de::Random& rng, BlendState& blendState)
1270 {
1271 if (rng.getBool())
1272 blendState.enableBlend = rng.getBool();
1273
1274 if (rng.getBool())
1275 {
1276 if (rng.getBool())
1277 blendState.blendEq = getRandomBlendEq(rng);
1278 else
1279 {
1280 const BlendEq rgb = getRandomBlendEq(rng);
1281 const BlendEq alpha = getRandomBlendEq(rng);
1282
1283 blendState.blendEq = SeparateBlendEq(rgb, alpha);
1284 }
1285 }
1286
1287 if (rng.getBool())
1288 {
1289 if (rng.getBool())
1290 blendState.blendFunc = getRandomBlendFunc(rng);
1291 else
1292 {
1293 const BlendFunc rgb = getRandomBlendFunc(rng);
1294 const BlendFunc alpha = getRandomBlendFunc(rng);
1295
1296 blendState.blendFunc = SeparateBlendFunc(rgb, alpha);
1297 }
1298 }
1299
1300 if (rng.getBool())
1301 {
1302 const bool red = rng.getBool();
1303 const bool green = rng.getBool();
1304 const bool blue = rng.getBool();
1305 const bool alpha = rng.getBool();
1306
1307 blendState.colorMask = BVec4(red, blue, green, alpha);
1308 }
1309 }
1310
getRandomFormat(de::Random & rng,Context & context)1311 TextureFormat getRandomFormat (de::Random& rng, Context& context)
1312 {
1313 const bool supportsES32orGL45 = checkES32orGL45Support(context);
1314
1315 const deUint32 glFormats[] =
1316 {
1317 GL_R8,
1318 GL_RG8,
1319 GL_RGB8,
1320 GL_RGB565,
1321 GL_RGBA4,
1322 GL_RGB5_A1,
1323 GL_RGBA8,
1324 GL_RGB10_A2,
1325 GL_RGB10_A2UI,
1326 GL_R8I,
1327 GL_R8UI,
1328 GL_R16I,
1329 GL_R16UI,
1330 GL_R32I,
1331 GL_R32UI,
1332 GL_RG8I,
1333 GL_RG8UI,
1334 GL_RG16I,
1335 GL_RG16UI,
1336 GL_RG32I,
1337 GL_RG32UI,
1338 GL_RGBA8I,
1339 GL_RGBA8UI,
1340 GL_RGBA16I,
1341 GL_RGBA16UI,
1342 GL_RGBA32I,
1343 GL_RGBA32UI,
1344 GL_RGBA16F,
1345 GL_R32F,
1346 GL_RG32F,
1347 GL_RGBA32F,
1348 GL_R11F_G11F_B10F
1349 };
1350
1351 if (supportsES32orGL45)
1352 return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % DE_LENGTH_OF_ARRAY(glFormats)));
1353 else
1354 {
1355 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(glFormats) == 32);
1356 return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % (DE_LENGTH_OF_ARRAY(glFormats) - 5)));
1357 }
1358 }
1359
genRandomTest(de::Random & rng,BlendState & preCommon,BlendState & postCommon,vector<DrawBufferInfo> & drawBuffers,int maxDrawBufferCount,Context & context)1360 void genRandomTest (de::Random& rng, BlendState& preCommon, BlendState& postCommon, vector<DrawBufferInfo>& drawBuffers, int maxDrawBufferCount, Context& context)
1361 {
1362 genRandomBlendState(rng, preCommon);
1363 genRandomBlendState(rng, postCommon);
1364
1365 for (int drawBufferNdx = 0; drawBufferNdx < maxDrawBufferCount; drawBufferNdx++)
1366 {
1367 const bool render = rng.getFloat() > 0.1f;
1368 const IVec2 size (64, 64);
1369 const TextureFormat format (getRandomFormat(rng, context));
1370 BlendState blendState;
1371
1372 genRandomBlendState(rng, blendState);
1373
1374 // 32bit float formats don't support blending in GLES32
1375 if (format.type == tcu::TextureFormat::FLOAT)
1376 {
1377 // If format is 32bit float post common can't enable blending
1378 if (postCommon.enableBlend && *postCommon.enableBlend)
1379 {
1380 // Either don't set enable blend or disable blending
1381 if (rng.getBool())
1382 postCommon.enableBlend = tcu::nothing<bool>();
1383 else
1384 postCommon.enableBlend = tcu::just(false);
1385 }
1386
1387 // If post common doesn't disable blending, per attachment state or
1388 // pre common must.
1389 if (!postCommon.enableBlend)
1390 {
1391 // If pre common enables blend per attachment must disable it
1392 // If per attachment state changes blend state it must disable it
1393 if ((preCommon.enableBlend && *preCommon.enableBlend)
1394 || blendState.enableBlend)
1395 blendState.enableBlend = tcu::just(false);
1396 }
1397 }
1398
1399 drawBuffers.push_back(DrawBufferInfo(render, size, blendState, format));
1400 }
1401 }
1402
1403 class MaxDrawBuffersIndexedTest : public TestCase
1404 {
1405 public:
1406 MaxDrawBuffersIndexedTest (Context& contet, int seed);
1407
1408 void init (void);
1409 IterateResult iterate (void);
1410
1411 private:
1412 const int m_seed;
1413 };
1414
MaxDrawBuffersIndexedTest(Context & context,int seed)1415 MaxDrawBuffersIndexedTest::MaxDrawBuffersIndexedTest (Context& context, int seed)
1416 : TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str())
1417 , m_seed (deInt32Hash(seed) ^ 1558001307u)
1418 {
1419 }
1420
init(void)1421 void MaxDrawBuffersIndexedTest::init (void)
1422 {
1423 const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
1424
1425 if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1426 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1427 }
1428
iterate(void)1429 TestCase::IterateResult MaxDrawBuffersIndexedTest::iterate (void)
1430 {
1431 TestLog& log = m_testCtx.getLog();
1432 tcu::ResultCollector results (log);
1433 de::Random rng (m_seed);
1434 BlendState preCommonBlendState;
1435 BlendState postCommonBlendState;
1436 vector<DrawBufferInfo> drawBuffers;
1437
1438 genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, 4, m_context);
1439
1440 runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
1441
1442 results.setTestContextResult(m_testCtx);
1443
1444 return STOP;
1445 }
1446
1447 class ImplMaxDrawBuffersIndexedTest : public TestCase
1448 {
1449 public:
1450 ImplMaxDrawBuffersIndexedTest (Context& contet, int seed);
1451
1452 void init (void);
1453 IterateResult iterate (void);
1454
1455 private:
1456 const int m_seed;
1457 };
1458
ImplMaxDrawBuffersIndexedTest(Context & context,int seed)1459 ImplMaxDrawBuffersIndexedTest::ImplMaxDrawBuffersIndexedTest (Context& context, int seed)
1460 : TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str())
1461 , m_seed (deInt32Hash(seed) ^ 2686315738u)
1462 {
1463 }
1464
init(void)1465 void ImplMaxDrawBuffersIndexedTest::init (void)
1466 {
1467 const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
1468
1469 if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1470 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1471 }
1472
iterate(void)1473 TestCase::IterateResult ImplMaxDrawBuffersIndexedTest::iterate (void)
1474 {
1475 TestLog& log = m_testCtx.getLog();
1476 tcu::ResultCollector results (log);
1477 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1478 de::Random rng (m_seed);
1479 deInt32 maxDrawBuffers = 0;
1480 BlendState preCommonBlendState;
1481 BlendState postCommonBlendState;
1482 vector<DrawBufferInfo> drawBuffers;
1483
1484 gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1485 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_DRAW_BUFFERS) failed");
1486
1487 TCU_CHECK(maxDrawBuffers > 0);
1488
1489 genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, maxDrawBuffers, m_context);
1490
1491 runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
1492
1493 results.setTestContextResult(m_testCtx);
1494
1495 return STOP;
1496 }
1497
1498 enum PrePost
1499 {
1500 PRE,
1501 POST
1502 };
1503
createDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)1504 TestCase* createDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
1505 {
1506 const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
1507
1508 if (prepost == PRE)
1509 {
1510 const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
1511 commonState.blendEq,
1512 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
1513 tcu::nothing<BVec4>());
1514 vector<DrawBufferInfo> drawBuffers;
1515
1516 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1517 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1518
1519 return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
1520 }
1521 else if (prepost == POST)
1522 {
1523 const BlendState preState = BlendState(just(true),
1524 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
1525 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
1526 tcu::nothing<BVec4>());
1527 vector<DrawBufferInfo> drawBuffers;
1528
1529 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1530 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1531
1532 return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
1533 }
1534 else
1535 {
1536 DE_ASSERT(false);
1537 return DE_NULL;
1538 }
1539 }
1540
createAdvancedEqDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)1541 TestCase* createAdvancedEqDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
1542 {
1543 const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
1544
1545 if (prepost == PRE)
1546 {
1547 const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
1548 commonState.blendEq,
1549 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
1550 tcu::nothing<BVec4>());
1551 vector<DrawBufferInfo> drawBuffers;
1552
1553 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1554
1555 return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
1556 }
1557 else if (prepost == POST)
1558 {
1559 const BlendState preState = BlendState(just(true),
1560 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
1561 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
1562 tcu::nothing<BVec4>());
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, commonState, drawBuffers, name, name);
1568 }
1569 else
1570 {
1571 DE_ASSERT(false);
1572 return DE_NULL;
1573 }
1574 }
1575
addDrawBufferCommonTests(TestCaseGroup * root,PrePost prepost)1576 void addDrawBufferCommonTests (TestCaseGroup* root, PrePost prepost)
1577 {
1578 const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1579
1580 {
1581 const BlendState disableState = BlendState(just(false), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1582 const BlendState enableState = BlendState(just(true), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1583
1584 root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_enable", enableState, enableState));
1585 root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_disable", disableState, disableState));
1586 root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_enable", disableState, enableState));
1587 root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_disable", enableState, disableState));
1588 }
1589
1590 {
1591 const BlendState eqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1592 const BlendState eqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1593
1594 const BlendState separateEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_ADD, GL_FUNC_SUBTRACT)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1595 const BlendState separateEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_SUBTRACT, GL_FUNC_ADD)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1596
1597 const BlendState advancedEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1598 const BlendState advancedEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_SCREEN), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1599
1600 root->addChild(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, separateEqStateB));
1602 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_advanced_blend_eq", eqStateA, advancedEqStateB));
1603
1604 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_blend_eq", separateEqStateA, eqStateB));
1605 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_separate_blend_eq", separateEqStateA, separateEqStateB));
1606 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_advanced_blend_eq", separateEqStateA, advancedEqStateB));
1607
1608 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_blend_eq", advancedEqStateA, eqStateB));
1609 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_separate_blend_eq", advancedEqStateA, separateEqStateB));
1610 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_advanced_blend_eq", advancedEqStateA, advancedEqStateB));
1611 }
1612
1613 {
1614 const BlendState funcStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>());
1615 const BlendState funcStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>());
1616 const BlendState separateFuncStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA), BlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA))), Maybe<BVec4>());
1617 const BlendState separateFuncStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA), BlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA))), Maybe<BVec4>());
1618
1619 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_blend_func", funcStateA, funcStateB));
1620 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_separate_blend_func", funcStateA, separateFuncStateB));
1621 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_blend_func", separateFuncStateA, funcStateB));
1622 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_separate_blend_func", separateFuncStateA, separateFuncStateB));
1623 }
1624
1625 {
1626 const BlendState commonColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false)));
1627 const BlendState bufferColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(false, true, false, true)));
1628
1629 root->addChild(createDiffTest(root->getContext(), prepost, "common_color_mask_buffer_color_mask", commonColorMaskState, bufferColorMaskState));
1630 }
1631 }
1632
addRandomMaxTest(TestCaseGroup * root)1633 void addRandomMaxTest (TestCaseGroup* root)
1634 {
1635 for (int i = 0; i < 20; i++)
1636 root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
1637 }
1638
addRandomImplMaxTest(TestCaseGroup * root)1639 void addRandomImplMaxTest (TestCaseGroup* root)
1640 {
1641 for (int i = 0; i < 20; i++)
1642 root->addChild(new ImplMaxDrawBuffersIndexedTest(root->getContext(), i));
1643 }
1644
1645 } // anonymous
1646
createDrawBuffersIndexedTests(Context & context)1647 TestCaseGroup* createDrawBuffersIndexedTests (Context& context)
1648 {
1649 const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1650 TestCaseGroup* const group = new TestCaseGroup(context, "draw_buffers_indexed", "Test for indexed draw buffers. GL_EXT_draw_buffers_indexed.");
1651
1652 TestCaseGroup* const preGroup = new TestCaseGroup(context, "overwrite_common", "Set common state and overwrite it with draw buffer blend state.");
1653 TestCaseGroup* const postGroup = new TestCaseGroup(context, "overwrite_indexed", "Set indexed blend state and overwrite it with common state.");
1654 TestCaseGroup* const randomGroup = new TestCaseGroup(context, "random", "Random indexed blend state tests.");
1655 TestCaseGroup* const maxGroup = new TestCaseGroup(context, "max_required_draw_buffers", "Random tests using minimum maximum number of draw buffers.");
1656 TestCaseGroup* const maxImplGroup = new TestCaseGroup(context, "max_implementation_draw_buffers", "Random tests using maximum number of draw buffers reported by implementation.");
1657
1658 group->addChild(preGroup);
1659 group->addChild(postGroup);
1660 group->addChild(randomGroup);
1661
1662 randomGroup->addChild(maxGroup);
1663 randomGroup->addChild(maxImplGroup);
1664
1665 addDrawBufferCommonTests(preGroup, PRE);
1666 addDrawBufferCommonTests(postGroup, POST);
1667 addRandomMaxTest(maxGroup);
1668 addRandomImplMaxTest(maxImplGroup);
1669
1670 return group;
1671 }
1672
1673 } // Functional
1674 } // gles31
1675 } // deqp
1676