1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2015 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Indexed blend operation tests (GL_EXT_draw_buffers_indexed)
22 *//*--------------------------------------------------------------------*/
24 #include "es31fDrawBuffersIndexedTests.hpp"
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"
34 #include "sglrReferenceUtils.hpp"
36 #include "rrMultisamplePixelBufferAccess.hpp"
37 #include "rrRenderer.hpp"
39 #include "glwEnums.hpp"
40 #include "glwFunctions.hpp"
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"
54 #include "deRandom.hpp"
55 #include "deArrayUtil.hpp"
56 #include "deStringUtil.hpp"
57 #include "deUniquePtr.hpp"
71 using tcu::TextureFormat;
72 using tcu::TextureLevel;
82 using sglr::rr_util::mapGLBlendEquation;
83 using sglr::rr_util::mapGLBlendFunc;
84 using sglr::rr_util::mapGLBlendEquationAdvanced;
95 typedef deUint32 BlendEq;
97 bool isAdvancedBlendEq (BlendEq eq)
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;
121 struct SeparateBlendEq
123 SeparateBlendEq (BlendEq rgb_, BlendEq alpha_)
135 BlendFunc (deUint32 src_, deUint32 dst_)
145 struct SeparateBlendFunc
147 SeparateBlendFunc (BlendFunc rgb_, BlendFunc alpha_)
157 typedef deUint32 DrawBuffer;
163 BlendState (const Maybe<bool>& enableBlend_,
164 const Maybe<Either<BlendEq, SeparateBlendEq> >& blendEq_,
165 const Maybe<Either<BlendFunc, SeparateBlendFunc> >& blendFunc_,
166 const Maybe<BVec4>& colorMask_)
167 : enableBlend (enableBlend_)
169 , blendFunc (blendFunc_)
170 , colorMask (colorMask_)
174 bool isEmpty (void) const
176 return (!enableBlend) && (!blendEq) && (!blendFunc) && (!colorMask);
179 Maybe<bool> enableBlend;
180 Maybe<Either<BlendEq, SeparateBlendEq> > blendEq;
181 Maybe<Either<BlendFunc, SeparateBlendFunc> > blendFunc;
182 Maybe<BVec4> colorMask;
185 void setCommonBlendState (const glw::Functions& gl, const BlendState& blend)
187 if (blend.enableBlend)
189 if (*blend.enableBlend)
192 gl.disable(GL_BLEND);
197 const BVec4& mask = *blend.colorMask;
199 gl.colorMask(mask.x(), mask.y(), mask.z(), mask.w());
204 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
206 if (blendEq.is<BlendEq>())
207 gl.blendEquation(blendEq.get<BlendEq>());
208 else if (blendEq.is<SeparateBlendEq>())
209 gl.blendEquationSeparate(blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
216 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
218 if (blendFunc.is<BlendFunc>())
219 gl.blendFunc(blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
220 else if (blendFunc.is<SeparateBlendFunc>())
221 gl.blendFuncSeparate(blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
226 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set common blend state.");
229 void setIndexedBlendState (const glw::Functions& gl, const BlendState& blend, deUint32 index)
231 if (blend.enableBlend)
233 if (*blend.enableBlend)
234 gl.enablei(GL_BLEND, index);
236 gl.disablei(GL_BLEND, index);
241 const BVec4 mask = *blend.colorMask;
243 gl.colorMaski(index, mask.x(), mask.y(), mask.z(), mask.w());
248 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
250 if (blendEq.is<BlendEq>())
251 gl.blendEquationi(index, blendEq.get<BlendEq>());
252 else if (blendEq.is<SeparateBlendEq>())
253 gl.blendEquationSeparatei(index, blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
260 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
262 if (blendFunc.is<BlendFunc>())
263 gl.blendFunci(index, blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
264 else if (blendFunc.is<SeparateBlendFunc>())
265 gl.blendFuncSeparatei(index, blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
270 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set draw buffer specifig blend state.");
276 DrawBufferInfo (bool render,
278 const BlendState& blendState,
279 const TextureFormat& format);
281 const TextureFormat& getFormat (void) const { return m_format; }
282 const IVec2& getSize (void) const { return m_size; }
283 const BlendState& getBlendState (void) const { return m_blendState; }
284 bool getRender (void) const { return m_render; }
289 TextureFormat m_format;
290 BlendState m_blendState;
293 DrawBufferInfo::DrawBufferInfo (bool render, const IVec2& size, const BlendState& blendState, const TextureFormat& format)
297 , m_blendState (blendState)
301 void clearRenderbuffer (const glw::Functions& gl,
302 const tcu::TextureFormat& format,
304 int renderbufferCount,
305 tcu::TextureLevel& refRenderbuffer)
307 const tcu::TextureFormatInfo info = tcu::getTextureFormatInfo(format);
309 // Clear each buffer to different color
310 const float redScale = float(renderbufferNdx + 1) / float(renderbufferCount);
311 const float blueScale = float(renderbufferCount - renderbufferNdx) / float(renderbufferCount);
312 const float greenScale = float(((renderbufferCount/2) + renderbufferNdx) % renderbufferCount) / float(renderbufferCount);
313 // Alpha should never be zero as advanced blend equations assume premultiplied alpha.
314 const float alphaScale = float(1 + (((renderbufferCount/2) + renderbufferCount - renderbufferNdx) % renderbufferCount)) / float(renderbufferCount);
316 switch (tcu::getTextureChannelClass(format.type))
318 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
320 const float red = -1000.0f + 2000.0f * redScale;
321 const float green = -1000.0f + 2000.0f * greenScale;
322 const float blue = -1000.0f + 2000.0f * blueScale;
323 const float alpha = -1000.0f + 2000.0f * alphaScale;
324 const Vec4 color (red, green, blue, alpha);
326 tcu::clear(refRenderbuffer, color);
327 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
331 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
333 const deInt32 red = deInt32(info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale);
334 const deInt32 green = deInt32(info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale);
335 const deInt32 blue = deInt32(info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale);
336 const deInt32 alpha = deInt32(info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale);
337 const IVec4 color (red, green, blue, alpha);
339 tcu::clear(refRenderbuffer, color);
340 gl.clearBufferiv(GL_COLOR, renderbufferNdx, color.getPtr());
344 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
346 const deUint32 red = deUint32(info.valueMax.x() * redScale);
347 const deUint32 green = deUint32(info.valueMax.y() * greenScale);
348 const deUint32 blue = deUint32(info.valueMax.z() * blueScale);
349 const deUint32 alpha = deUint32(info.valueMax.w() * alphaScale);
350 const UVec4 color (red, green, blue, alpha);
352 tcu::clear(refRenderbuffer, color);
353 gl.clearBufferuiv(GL_COLOR, renderbufferNdx, color.getPtr());
357 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
359 const float red = info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale;
360 const float green = info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale;
361 const float blue = info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale;
362 const float alpha = info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale;
363 const Vec4 color (red, green, blue, alpha);
365 tcu::clear(refRenderbuffer, color);
366 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
370 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
372 const float red = info.valueMax.x() * redScale;
373 const float green = info.valueMax.y() * greenScale;
374 const float blue = info.valueMax.z() * blueScale;
375 const float alpha = info.valueMax.w() * alphaScale;
376 const Vec4 color (red, green, blue, alpha);
378 tcu::clear(refRenderbuffer, color);
379 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
387 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer.");
390 void genRenderbuffers (const glw::Functions& gl,
391 const vector<DrawBufferInfo>& drawBuffers,
392 const glu::Framebuffer& framebuffer,
393 const glu::RenderbufferVector& renderbuffers,
394 vector<TextureLevel>& refRenderbuffers)
396 vector<deUint32> bufs;
398 bufs.resize(drawBuffers.size());
400 DE_ASSERT(drawBuffers.size() == renderbuffers.size());
401 DE_ASSERT(drawBuffers.size() == refRenderbuffers.size());
403 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
405 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
407 const DrawBufferInfo& drawBuffer = drawBuffers[renderbufferNdx];
408 const TextureFormat& format = drawBuffer.getFormat();
409 const IVec2& size = drawBuffer.getSize();
410 const deUint32 glFormat = glu::getInternalFormat(format);
412 bufs[renderbufferNdx] = GL_COLOR_ATTACHMENT0 + renderbufferNdx;
413 refRenderbuffers[renderbufferNdx] = TextureLevel(drawBuffer.getFormat(), size.x(), size.y());
415 gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
416 gl.renderbufferStorage(GL_RENDERBUFFER, glFormat, size.x(), size.y());
417 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + renderbufferNdx, GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
418 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create renderbuffer.");
421 gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
423 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
425 const DrawBufferInfo& drawBuffer = drawBuffers[renderbufferNdx];
426 const TextureFormat& format = drawBuffer.getFormat();
428 clearRenderbuffer(gl, format, renderbufferNdx, (int)refRenderbuffers.size(), refRenderbuffers[renderbufferNdx]);
431 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
432 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
435 Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
437 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
438 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
440 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
441 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
443 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
444 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
446 const tcu::IVec4 srcBits = tcu::getTextureFormatBitDepth(sourceFormat);
447 const tcu::IVec4 readBits = tcu::getTextureFormatBitDepth(readPixelsFormat);
449 return Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
452 UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
454 const tcu::IVec4 srcMantissaBits = tcu::getTextureFormatMantissaBitDepth(sourceFormat);
455 const tcu::IVec4 readMantissaBits = tcu::getTextureFormatMantissaBitDepth(readPixelsFormat);
456 tcu::IVec4 ULPDiff(0);
458 for (int i = 0; i < 4; i++)
459 if (readMantissaBits[i] >= srcMantissaBits[i])
460 ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i];
462 return UVec4(4) * (UVec4(1) << (ULPDiff.cast<deUint32>()));
465 void verifyRenderbuffer (TestLog& log,
466 tcu::ResultCollector& results,
467 const tcu::TextureFormat& format,
469 const tcu::TextureLevel& refRenderbuffer,
470 const tcu::TextureLevel& result)
472 switch (tcu::getTextureChannelClass(format.type))
474 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
476 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
477 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
478 const UVec4 threshold = getFloatULPThreshold(format, result.getFormat());
480 if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
481 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
486 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
487 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
489 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
490 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
491 const UVec4 threshold (1, 1, 1, 1);
493 if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
494 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
499 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
500 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
502 const string name = "Renderbuffer" + de::toString(renderbufferNdx);
503 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
504 const Vec4 threshold = getFixedPointFormatThreshold(format, result.getFormat());
506 if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
507 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
517 TextureFormat getReadPixelFormat (const TextureFormat& format)
519 switch (tcu::getTextureChannelClass(format.type))
521 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
522 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32);
524 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
525 return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32);
527 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
528 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
529 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
531 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
532 return TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT);
536 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
540 void verifyRenderbuffers (TestLog& log,
541 tcu::ResultCollector& results,
542 glu::RenderContext& renderContext,
543 const glu::RenderbufferVector& renderbuffers,
544 const glu::Framebuffer& framebuffer,
545 const vector<TextureLevel>& refRenderbuffers)
547 const glw::Functions& gl = renderContext.getFunctions();
549 DE_ASSERT(renderbuffers.size() == refRenderbuffers.size());
551 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
553 for (int renderbufferNdx = 0; renderbufferNdx < (int)renderbuffers.size(); renderbufferNdx++)
555 const TextureLevel& refRenderbuffer = refRenderbuffers[renderbufferNdx];
556 const int width = refRenderbuffer.getWidth();
557 const int height = refRenderbuffer.getHeight();
558 const TextureFormat format = refRenderbuffer.getFormat();
560 tcu::TextureLevel result (getReadPixelFormat(format), width, height);
562 gl.readBuffer(GL_COLOR_ATTACHMENT0 + renderbufferNdx);
563 glu::readPixels(renderContext, 0, 0, result.getAccess());
564 GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels from renderbuffer failed.");
566 verifyRenderbuffer(log, results, format, renderbufferNdx, refRenderbuffer, result);
569 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
572 static const float s_quadCoords[] =
583 void setBlendState (rr::FragmentOperationState& fragOps, const BlendState& state)
587 if (state.blendEq->is<BlendEq>())
589 if (isAdvancedBlendEq(state.blendEq->get<BlendEq>()))
591 const rr::BlendEquationAdvanced equation = mapGLBlendEquationAdvanced(state.blendEq->get<BlendEq>());
593 fragOps.blendMode = rr::BLENDMODE_ADVANCED;
594 fragOps.blendEquationAdvaced = equation;
598 const rr::BlendEquation equation = mapGLBlendEquation(state.blendEq->get<BlendEq>());
600 fragOps.blendMode = rr::BLENDMODE_STANDARD;
601 fragOps.blendRGBState.equation = equation;
602 fragOps.blendAState.equation = equation;
607 DE_ASSERT(state.blendEq->is<SeparateBlendEq>());
609 fragOps.blendMode = rr::BLENDMODE_STANDARD;
610 fragOps.blendRGBState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().rgb);
611 fragOps.blendAState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().alpha);
617 if (state.blendFunc->is<BlendFunc>())
619 const rr::BlendFunc srcFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().src);
620 const rr::BlendFunc dstFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().dst);
622 fragOps.blendRGBState.srcFunc = srcFunction;
623 fragOps.blendRGBState.dstFunc = dstFunction;
625 fragOps.blendAState.srcFunc = srcFunction;
626 fragOps.blendAState.dstFunc = dstFunction;
630 DE_ASSERT(state.blendFunc->is<SeparateBlendFunc>());
632 fragOps.blendRGBState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.src);
633 fragOps.blendRGBState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.dst);
635 fragOps.blendAState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.src);
636 fragOps.blendAState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.dst);
641 fragOps.colorMask = *state.colorMask;
644 rr::RenderState createRenderState (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const DrawBufferInfo& info)
646 const IVec2 size = info.getSize();
647 rr::RenderState state (rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y())));
649 state.fragOps.blendMode = rr::BLENDMODE_STANDARD;
651 setBlendState(state.fragOps, preCommonBlendState);
652 setBlendState(state.fragOps, info.getBlendState());
653 setBlendState(state.fragOps, postCommonBlendState);
655 if (postCommonBlendState.enableBlend)
656 state.fragOps.blendMode = (*(postCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
657 else if (info.getBlendState().enableBlend)
658 state.fragOps.blendMode = (*(info.getBlendState().enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
659 else if (preCommonBlendState.enableBlend)
660 state.fragOps.blendMode = (*(preCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
662 state.fragOps.blendMode = rr::BLENDMODE_NONE;
664 if (tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
665 && tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
666 && tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
667 state.fragOps.blendMode = rr::BLENDMODE_NONE;
672 class VertexShader : public rr::VertexShader
676 virtual void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
679 VertexShader::VertexShader (void)
680 : rr::VertexShader (1, 1)
682 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
683 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
686 void VertexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
688 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
690 rr::VertexPacket& packet = *packets[packetNdx];
692 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
693 packet.outputs[0] = 0.5f * (Vec4(1.0f) + rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx));
697 class FragmentShader : public rr::FragmentShader
700 FragmentShader (int drawBufferNdx, const DrawBufferInfo& info);
701 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
704 const int m_drawBufferNdx;
705 const DrawBufferInfo m_info;
708 FragmentShader::FragmentShader (int drawBufferNdx, const DrawBufferInfo& info)
709 : rr::FragmentShader (1, 1)
710 , m_drawBufferNdx (drawBufferNdx)
713 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
715 switch (tcu::getTextureChannelClass(m_info.getFormat().type))
717 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
718 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
719 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
720 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
723 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
724 m_outputs[0].type = rr::GENERICVECTYPE_UINT32;
727 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
728 m_outputs[0].type = rr::GENERICVECTYPE_INT32;
736 void FragmentShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
738 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
740 rr::FragmentPacket& packet = packets[packetNdx];
742 DE_ASSERT(m_drawBufferNdx >= 0);
745 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
747 const Vec2 vColor = rr::readVarying<float>(packet, context, 0, fragNdx).xy();
748 const float values[] =
756 switch (tcu::getTextureChannelClass(m_info.getFormat().type))
758 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
759 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
760 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
762 const Vec4 color (values[(m_drawBufferNdx + 0) % 4],
763 values[(m_drawBufferNdx + 1) % 4],
764 values[(m_drawBufferNdx + 2) % 4],
765 values[(m_drawBufferNdx + 3) % 4]);
767 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
771 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
773 const UVec4 color ((deUint32)(values[(m_drawBufferNdx + 0) % 4]),
774 (deUint32)(values[(m_drawBufferNdx + 1) % 4]),
775 (deUint32)(values[(m_drawBufferNdx + 2) % 4]),
776 (deUint32)(values[(m_drawBufferNdx + 3) % 4]));
778 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
782 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
784 const IVec4 color ((deInt32)(values[(m_drawBufferNdx + 0) % 4]),
785 (deInt32)(values[(m_drawBufferNdx + 1) % 4]),
786 (deInt32)(values[(m_drawBufferNdx + 2) % 4]),
787 (deInt32)(values[(m_drawBufferNdx + 3) % 4]));
789 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
800 rr::VertexAttrib createVertexAttrib (const float* coords)
802 rr::VertexAttrib attrib;
804 attrib.type = rr::VERTEXATTRIBTYPE_FLOAT;
806 attrib.pointer = coords;
811 void renderRefQuad (const BlendState& preCommonBlendState,
812 const BlendState& postCommonBlendState,
813 const vector<DrawBufferInfo>& drawBuffers,
814 vector<TextureLevel>& refRenderbuffers)
816 const rr::Renderer renderer;
817 const rr::PrimitiveList primitives (rr::PRIMITIVETYPE_TRIANGLES, 6, 0);
818 const rr::VertexAttrib vertexAttribs[] =
820 createVertexAttrib(s_quadCoords)
823 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
825 if (drawBuffers[drawBufferNdx].getRender())
827 const rr::RenderState renderState (createRenderState(preCommonBlendState, postCommonBlendState, drawBuffers[drawBufferNdx]));
828 const rr::RenderTarget renderTarget (rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refRenderbuffers[drawBufferNdx].getAccess()));
829 const VertexShader vertexShader;
830 const FragmentShader fragmentShader (drawBufferNdx, drawBuffers[drawBufferNdx]);
831 const rr::Program program (&vertexShader, &fragmentShader);
832 const rr::DrawCommand command (renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, primitives);
834 renderer.draw(command);
839 bool requiresAdvancedBlendEq (const BlendState& pre, const BlendState post, const vector<DrawBufferInfo>& drawBuffers)
841 bool requiresAdvancedBlendEq = false;
843 if (pre.blendEq && pre.blendEq->is<BlendEq>())
844 requiresAdvancedBlendEq |= isAdvancedBlendEq(pre.blendEq->get<BlendEq>());
846 if (post.blendEq && post.blendEq->is<BlendEq>())
847 requiresAdvancedBlendEq |= isAdvancedBlendEq(post.blendEq->get<BlendEq>());
849 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
851 const BlendState& drawBufferBlendState = drawBuffers[drawBufferNdx].getBlendState();
853 if (drawBufferBlendState.blendEq && drawBufferBlendState.blendEq->is<BlendEq>())
854 requiresAdvancedBlendEq |= isAdvancedBlendEq(drawBufferBlendState.blendEq->get<BlendEq>());
857 return requiresAdvancedBlendEq;
860 glu::VertexSource genVertexSource (glu::RenderContext& renderContext)
862 const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
864 const char* const vertexSource =
865 "${GLSL_VERSION_DECL}\n"
866 "layout(location=0) in highp vec2 i_coord;\n"
867 "out highp vec2 v_color;\n"
870 "\tv_color = 0.5 * (vec2(1.0) + i_coord);\n"
871 "\tgl_Position = vec4(i_coord, 0.0, 1.0);\n"
874 map<string, string> args;
875 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
877 return glu::VertexSource(tcu::StringTemplate(vertexSource).specialize(args));
880 glu::FragmentSource genFragmentSource (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
882 std::ostringstream stream;
883 const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
885 stream << "${GLSL_VERSION_DECL}\n";
887 if (requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers))
889 stream << "${GLSL_EXTENSION}"
890 << "layout(blend_support_all_equations) out;\n";
893 stream << "in highp vec2 v_color;\n";
895 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
897 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
898 const TextureFormat& format = drawBuffer.getFormat();
900 stream << "layout(location=" << drawBufferNdx << ") out highp ";
902 switch (tcu::getTextureChannelClass(format.type))
904 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
905 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
906 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
910 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
914 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
922 stream << " o_drawBuffer" << drawBufferNdx << ";\n";
925 stream << "void main (void)\n"
928 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
930 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
931 const TextureFormat& format = drawBuffer.getFormat();
932 const char* const values[] =
940 stream << "\to_drawBuffer" << drawBufferNdx;
942 switch (tcu::getTextureChannelClass(format.type))
944 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
945 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
946 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
947 stream << " = vec4(" << values[(drawBufferNdx + 0) % 4]
948 << ", " << values[(drawBufferNdx + 1) % 4]
949 << ", " << values[(drawBufferNdx + 2) % 4]
950 << ", " << values[(drawBufferNdx + 3) % 4] << ");\n";
953 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
954 stream << " = uvec4(uint(" << values[(drawBufferNdx + 0) % 4]
955 << "), uint(" << values[(drawBufferNdx + 1) % 4]
956 << "), uint(" << values[(drawBufferNdx + 2) % 4]
957 << "), uint(" << values[(drawBufferNdx + 3) % 4] << "));\n";
960 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
961 stream << " = ivec4(int(" << values[(drawBufferNdx + 0) % 4]
962 << "), int(" << values[(drawBufferNdx + 1) % 4]
963 << "), int(" << values[(drawBufferNdx + 2) % 4]
964 << "), int(" << values[(drawBufferNdx + 3) % 4] << "));\n";
974 map<string, string> args;
975 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
976 args["GLSL_EXTENSION"] = supportsES32 ? "\n" : "#extension GL_KHR_blend_equation_advanced : require\n";
978 return glu::FragmentSource(tcu::StringTemplate(stream.str()).specialize(args));
981 glu::ProgramSources genShaderSources (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
983 return glu::ProgramSources() << genVertexSource(renderContext) << genFragmentSource(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext);
986 void renderGLQuad (glu::RenderContext& renderContext,
987 const glu::ShaderProgram& program)
989 const glu::VertexArrayBinding vertexArrays[] =
991 glu::VertexArrayBinding(glu::BindingPoint(0), glu::VertexArrayPointer(glu::VTX_COMP_FLOAT, glu::VTX_COMP_CONVERT_NONE, 2, 6, 0, s_quadCoords))
994 glu::draw(renderContext, program.getProgram(), 1, vertexArrays, glu::pr::Triangles(6));
997 void renderQuad (TestLog& log,
998 glu::RenderContext& renderContext,
999 const BlendState& preCommonBlendState,
1000 const BlendState& postCommonBlendState,
1001 const vector<DrawBufferInfo>& drawBuffers,
1002 const glu::Framebuffer& framebuffer,
1003 vector<TextureLevel>& refRenderbuffers)
1005 const glw::Functions& gl = renderContext.getFunctions();
1006 const glu::ShaderProgram program (gl, genShaderSources(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext));
1007 const IVec2 size = drawBuffers[0].getSize();
1008 const bool requiresBlendBarriers = requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers);
1010 vector<deUint32> bufs;
1012 bufs.resize(drawBuffers.size());
1014 for (int bufNdx = 0; bufNdx < (int)bufs.size(); bufNdx++)
1015 bufs[bufNdx] = (drawBuffers[bufNdx].getRender() ? GL_COLOR_ATTACHMENT0 + bufNdx : GL_NONE);
1019 gl.viewport(0, 0, size.x(), size.y());
1020 gl.useProgram(program.getProgram());
1021 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
1023 setCommonBlendState(gl, preCommonBlendState);
1025 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
1026 setIndexedBlendState(gl, drawBuffers[renderbufferNdx].getBlendState(), renderbufferNdx);
1028 setCommonBlendState(gl, postCommonBlendState);
1030 gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
1032 if (requiresBlendBarriers)
1035 renderGLQuad(renderContext, program);
1037 if (requiresBlendBarriers)
1040 gl.drawBuffers(0, 0);
1041 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1044 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
1046 renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, refRenderbuffers);
1049 void logBlendState (TestLog& log,
1050 const BlendState& blend)
1052 if (blend.enableBlend)
1054 if (*blend.enableBlend)
1055 log << TestLog::Message << "Enable blending." << TestLog::EndMessage;
1057 log << TestLog::Message << "Disable blending." << TestLog::EndMessage;
1060 if (blend.colorMask)
1062 const BVec4 mask = *blend.colorMask;
1064 log << TestLog::Message << "Set color mask: " << mask << "." << TestLog::EndMessage;
1069 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
1071 if (blendEq.is<BlendEq>())
1072 log << TestLog::Message << "Set blend equation: " << glu::getBlendEquationStr(blendEq.get<BlendEq>()) << "." << TestLog::EndMessage;
1073 else if (blendEq.is<SeparateBlendEq>())
1074 log << TestLog::Message << "Set blend equation rgb: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().rgb) << ", alpha: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().alpha) << "." << TestLog::EndMessage;
1079 if (blend.blendFunc)
1081 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
1083 if (blendFunc.is<BlendFunc>())
1084 log << TestLog::Message << "Set blend function source: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().dst) << "." << TestLog::EndMessage;
1085 else if (blendFunc.is<SeparateBlendFunc>())
1087 log << TestLog::Message << "Set blend function rgb source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.dst) << "." << TestLog::EndMessage;
1088 log << TestLog::Message << "Set blend function alpha source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.dst) << "." << TestLog::EndMessage;
1095 void logTestCaseInfo (TestLog& log,
1096 const BlendState& preCommonBlendState,
1097 const BlendState& postCommonBlendState,
1098 const vector<DrawBufferInfo>& drawBuffers)
1101 tcu::ScopedLogSection drawBuffersSection(log, "DrawBuffers", "Draw buffers");
1103 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
1105 const tcu::ScopedLogSection drawBufferSection (log, "DrawBuffer" + de::toString(drawBufferNdx), "Draw Buffer " + de::toString(drawBufferNdx));
1106 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
1108 log << TestLog::Message << "Format: " << drawBuffer.getFormat() << TestLog::EndMessage;
1109 log << TestLog::Message << "Size: " << drawBuffer.getSize() << TestLog::EndMessage;
1110 log << TestLog::Message << "Render: " << (drawBuffer.getRender() ? "true" : "false") << TestLog::EndMessage;
1114 if (!preCommonBlendState.isEmpty())
1116 tcu::ScopedLogSection s(log, "PreCommonState", "First set common blend state");
1117 logBlendState(log, preCommonBlendState);
1120 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
1122 if (!drawBuffers[drawBufferNdx].getBlendState().isEmpty())
1124 const tcu::ScopedLogSection s(log, "DrawBufferState" + de::toString(drawBufferNdx), "Set DrawBuffer " + de::toString(drawBufferNdx) + " state to");
1126 logBlendState(log, drawBuffers[drawBufferNdx].getBlendState());
1130 if (!postCommonBlendState.isEmpty())
1132 tcu::ScopedLogSection s(log, "PostCommonState", "After set common blend state");
1133 logBlendState(log, postCommonBlendState);
1137 void runTest (TestLog& log,
1138 tcu::ResultCollector& results,
1139 glu::RenderContext& renderContext,
1141 const BlendState& preCommonBlendState,
1142 const BlendState& postCommonBlendState,
1143 const vector<DrawBufferInfo>& drawBuffers)
1145 const glw::Functions& gl = renderContext.getFunctions();
1146 glu::RenderbufferVector renderbuffers (gl, drawBuffers.size());
1147 glu::Framebuffer framebuffer (gl);
1148 vector<TextureLevel> refRenderbuffers (drawBuffers.size());
1150 logTestCaseInfo(log, preCommonBlendState, postCommonBlendState, drawBuffers);
1152 genRenderbuffers(gl, drawBuffers, framebuffer, renderbuffers, refRenderbuffers);
1154 renderQuad(log, renderContext, preCommonBlendState, postCommonBlendState, drawBuffers, framebuffer, refRenderbuffers);
1156 verifyRenderbuffers(log, results, renderContext, renderbuffers, framebuffer, refRenderbuffers);
1159 class DrawBuffersIndexedTest : public TestCase
1162 DrawBuffersIndexedTest (Context& context,
1163 const BlendState& preCommonBlendState,
1164 const BlendState& postCommonBlendState,
1165 const vector<DrawBufferInfo>& drawBuffers,
1167 const string& description);
1170 IterateResult iterate (void);
1173 const BlendState m_preCommonBlendState;
1174 const BlendState m_postCommonBlendState;
1175 const vector<DrawBufferInfo> m_drawBuffers;
1178 DrawBuffersIndexedTest::DrawBuffersIndexedTest (Context& context,
1179 const BlendState& preCommonBlendState,
1180 const BlendState& postCommonBlendState,
1181 const vector<DrawBufferInfo>& drawBuffers,
1183 const string& description)
1184 : TestCase (context, name.c_str(), description.c_str())
1185 , m_preCommonBlendState (preCommonBlendState)
1186 , m_postCommonBlendState (postCommonBlendState)
1187 , m_drawBuffers (drawBuffers)
1191 void DrawBuffersIndexedTest::init (void)
1193 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1197 if (requiresAdvancedBlendEq(m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers) && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
1198 TCU_THROW(NotSupportedError, "Extension GL_KHR_blend_equation_advanced not supported");
1200 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1201 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1205 TestCase::IterateResult DrawBuffersIndexedTest::iterate (void)
1207 TestLog& log = m_testCtx.getLog();
1208 tcu::ResultCollector results (log);
1210 runTest(log, results, m_context.getRenderContext(), m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers);
1212 results.setTestContextResult(m_testCtx);
1217 BlendEq getRandomBlendEq (de::Random& rng)
1219 const BlendEq eqs[] =
1223 GL_FUNC_REVERSE_SUBTRACT,
1228 return de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(eqs)>(eqs, rng.getUint32() % DE_LENGTH_OF_ARRAY(eqs));
1231 BlendFunc getRandomBlendFunc (de::Random& rng)
1233 const deUint32 funcs[] =
1238 GL_ONE_MINUS_SRC_COLOR,
1240 GL_ONE_MINUS_DST_COLOR,
1242 GL_ONE_MINUS_SRC_ALPHA,
1244 GL_ONE_MINUS_DST_ALPHA,
1246 GL_ONE_MINUS_CONSTANT_COLOR,
1248 GL_ONE_MINUS_CONSTANT_ALPHA,
1249 GL_SRC_ALPHA_SATURATE
1252 const deUint32 src = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
1253 const deUint32 dst = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
1255 return BlendFunc(src, dst);
1258 void genRandomBlendState (de::Random& rng, BlendState& blendState)
1261 blendState.enableBlend = rng.getBool();
1266 blendState.blendEq = getRandomBlendEq(rng);
1269 const BlendEq rgb = getRandomBlendEq(rng);
1270 const BlendEq alpha = getRandomBlendEq(rng);
1272 blendState.blendEq = SeparateBlendEq(rgb, alpha);
1279 blendState.blendFunc = getRandomBlendFunc(rng);
1282 const BlendFunc rgb = getRandomBlendFunc(rng);
1283 const BlendFunc alpha = getRandomBlendFunc(rng);
1285 blendState.blendFunc = SeparateBlendFunc(rgb, alpha);
1291 const bool red = rng.getBool();
1292 const bool green = rng.getBool();
1293 const bool blue = rng.getBool();
1294 const bool alpha = rng.getBool();
1296 blendState.colorMask = BVec4(red, blue, green, alpha);
1300 TextureFormat getRandomFormat (de::Random& rng, Context& context)
1302 const bool supportsES32 = glu::contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1304 const deUint32 glFormats[] =
1341 return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % DE_LENGTH_OF_ARRAY(glFormats)));
1344 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(glFormats) == 32);
1345 return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % (DE_LENGTH_OF_ARRAY(glFormats) - 5)));
1349 void genRandomTest (de::Random& rng, BlendState& preCommon, BlendState& postCommon, vector<DrawBufferInfo>& drawBuffers, int maxDrawBufferCount, Context& context)
1351 genRandomBlendState(rng, preCommon);
1352 genRandomBlendState(rng, postCommon);
1354 for (int drawBufferNdx = 0; drawBufferNdx < maxDrawBufferCount; drawBufferNdx++)
1356 const bool render = rng.getFloat() > 0.1f;
1357 const IVec2 size (64, 64);
1358 const TextureFormat format (getRandomFormat(rng, context));
1359 BlendState blendState;
1361 genRandomBlendState(rng, blendState);
1363 // 32bit float formats don't support blending in GLES32
1364 if (format.type == tcu::TextureFormat::FLOAT)
1366 // If format is 32bit float post common can't enable blending
1367 if (postCommon.enableBlend && *postCommon.enableBlend)
1369 // Either don't set enable blend or disable blending
1371 postCommon.enableBlend = tcu::nothing<bool>();
1373 postCommon.enableBlend = tcu::just(false);
1376 // If post common doesn't disable blending, per attachment state or
1378 if (!postCommon.enableBlend)
1380 // If pre common enables blend per attachment must disable it
1381 // If per attachment state changes blend state it must disable it
1382 if ((preCommon.enableBlend && *preCommon.enableBlend)
1383 || blendState.enableBlend)
1384 blendState.enableBlend = tcu::just(false);
1388 drawBuffers.push_back(DrawBufferInfo(render, size, blendState, format));
1392 class MaxDrawBuffersIndexedTest : public TestCase
1395 MaxDrawBuffersIndexedTest (Context& contet, int seed);
1398 IterateResult iterate (void);
1404 MaxDrawBuffersIndexedTest::MaxDrawBuffersIndexedTest (Context& context, int seed)
1405 : TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str())
1406 , m_seed (deInt32Hash(seed) ^ 1558001307u)
1410 void MaxDrawBuffersIndexedTest::init (void)
1412 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1414 if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1415 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1418 TestCase::IterateResult MaxDrawBuffersIndexedTest::iterate (void)
1420 TestLog& log = m_testCtx.getLog();
1421 tcu::ResultCollector results (log);
1422 de::Random rng (m_seed);
1423 BlendState preCommonBlendState;
1424 BlendState postCommonBlendState;
1425 vector<DrawBufferInfo> drawBuffers;
1427 genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, 4, m_context);
1429 runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
1431 results.setTestContextResult(m_testCtx);
1436 class ImplMaxDrawBuffersIndexedTest : public TestCase
1439 ImplMaxDrawBuffersIndexedTest (Context& contet, int seed);
1442 IterateResult iterate (void);
1448 ImplMaxDrawBuffersIndexedTest::ImplMaxDrawBuffersIndexedTest (Context& context, int seed)
1449 : TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str())
1450 , m_seed (deInt32Hash(seed) ^ 2686315738u)
1454 void ImplMaxDrawBuffersIndexedTest::init (void)
1456 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1458 if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1459 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1462 TestCase::IterateResult ImplMaxDrawBuffersIndexedTest::iterate (void)
1464 TestLog& log = m_testCtx.getLog();
1465 tcu::ResultCollector results (log);
1466 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1467 de::Random rng (m_seed);
1468 deInt32 maxDrawBuffers = 0;
1469 BlendState preCommonBlendState;
1470 BlendState postCommonBlendState;
1471 vector<DrawBufferInfo> drawBuffers;
1473 gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1474 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_DRAW_BUFFERS) failed");
1476 TCU_CHECK(maxDrawBuffers > 0);
1478 genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, maxDrawBuffers, m_context);
1480 runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
1482 results.setTestContextResult(m_testCtx);
1493 TestCase* createDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
1495 const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
1499 const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
1500 commonState.blendEq,
1501 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
1502 tcu::nothing<BVec4>());
1503 vector<DrawBufferInfo> drawBuffers;
1505 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1506 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1508 return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
1510 else if (prepost == POST)
1512 const BlendState preState = BlendState(just(true),
1513 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
1514 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
1515 tcu::nothing<BVec4>());
1516 vector<DrawBufferInfo> drawBuffers;
1518 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1519 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1521 return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
1530 TestCase* createAdvancedEqDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
1532 const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
1536 const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
1537 commonState.blendEq,
1538 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
1539 tcu::nothing<BVec4>());
1540 vector<DrawBufferInfo> drawBuffers;
1542 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1544 return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
1546 else if (prepost == POST)
1548 const BlendState preState = BlendState(just(true),
1549 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
1550 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
1551 tcu::nothing<BVec4>());
1552 vector<DrawBufferInfo> drawBuffers;
1554 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1556 return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
1565 void addDrawBufferCommonTests (TestCaseGroup* root, PrePost prepost)
1567 const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1570 const BlendState disableState = BlendState(just(false), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1571 const BlendState enableState = BlendState(just(true), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1573 root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_enable", enableState, enableState));
1574 root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_disable", disableState, disableState));
1575 root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_enable", disableState, enableState));
1576 root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_disable", enableState, disableState));
1580 const BlendState eqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1581 const BlendState eqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1583 const BlendState separateEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_ADD, GL_FUNC_SUBTRACT)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1584 const BlendState separateEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_SUBTRACT, GL_FUNC_ADD)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1586 const BlendState advancedEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1587 const BlendState advancedEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_SCREEN), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1589 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_blend_eq", eqStateA, eqStateB));
1590 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_separate_blend_eq", eqStateA, separateEqStateB));
1591 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_advanced_blend_eq", eqStateA, advancedEqStateB));
1593 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_blend_eq", separateEqStateA, eqStateB));
1594 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_separate_blend_eq", separateEqStateA, separateEqStateB));
1595 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_advanced_blend_eq", separateEqStateA, advancedEqStateB));
1597 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_blend_eq", advancedEqStateA, eqStateB));
1598 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_separate_blend_eq", advancedEqStateA, separateEqStateB));
1599 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_advanced_blend_eq", advancedEqStateA, advancedEqStateB));
1603 const BlendState funcStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>());
1604 const BlendState funcStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>());
1605 const BlendState separateFuncStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA), BlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA))), Maybe<BVec4>());
1606 const BlendState separateFuncStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA), BlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA))), Maybe<BVec4>());
1608 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_blend_func", funcStateA, funcStateB));
1609 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_separate_blend_func", funcStateA, separateFuncStateB));
1610 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_blend_func", separateFuncStateA, funcStateB));
1611 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_separate_blend_func", separateFuncStateA, separateFuncStateB));
1615 const BlendState commonColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false)));
1616 const BlendState bufferColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(false, true, false, true)));
1618 root->addChild(createDiffTest(root->getContext(), prepost, "common_color_mask_buffer_color_mask", commonColorMaskState, bufferColorMaskState));
1622 void addRandomMaxTest (TestCaseGroup* root)
1624 for (int i = 0; i < 20; i++)
1625 root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
1628 void addRandomImplMaxTest (TestCaseGroup* root)
1630 for (int i = 0; i < 20; i++)
1631 root->addChild(new ImplMaxDrawBuffersIndexedTest(root->getContext(), i));
1636 TestCaseGroup* createDrawBuffersIndexedTests (Context& context)
1638 const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1639 TestCaseGroup* const group = new TestCaseGroup(context, "draw_buffers_indexed", "Test for indexed draw buffers. GL_EXT_draw_buffers_indexed.");
1641 TestCaseGroup* const preGroup = new TestCaseGroup(context, "overwrite_common", "Set common state and overwrite it with draw buffer blend state.");
1642 TestCaseGroup* const postGroup = new TestCaseGroup(context, "overwrite_indexed", "Set indexed blend state and overwrite it with common state.");
1643 TestCaseGroup* const randomGroup = new TestCaseGroup(context, "random", "Random indexed blend state tests.");
1644 TestCaseGroup* const maxGroup = new TestCaseGroup(context, "max_required_draw_buffers", "Random tests using minimum maximum number of draw buffers.");
1645 TestCaseGroup* const maxImplGroup = new TestCaseGroup(context, "max_implementation_draw_buffers", "Random tests using maximum number of draw buffers reported by implementation.");
1647 group->addChild(preGroup);
1648 group->addChild(postGroup);
1649 group->addChild(randomGroup);
1651 randomGroup->addChild(maxGroup);
1652 randomGroup->addChild(maxImplGroup);
1654 addDrawBufferCommonTests(preGroup, PRE);
1655 addDrawBufferCommonTests(postGroup, POST);
1656 addRandomMaxTest(maxGroup);
1657 addRandomImplMaxTest(maxImplGroup);