1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*------------------------------------------------------------------------- 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * drawElements Quality Program Reference Renderer 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * ----------------------------------------------- 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright 2014 The Android Open Source Project 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Licensed under the Apache License, Version 2.0 (the "License"); 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * you may not use this file except in compliance with the License. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * You may obtain a copy of the License at 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * http://www.apache.org/licenses/LICENSE-2.0 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Unless required by applicable law or agreed to in writing, software 14a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org * distributed under the License is distributed on an "AS IS" BASIS, 15a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * See the License for the specific language governing permissions and 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * limitations under the License. 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *//*! 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * \file 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * \brief Reference implementation for per-fragment operations. 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *//*--------------------------------------------------------------------*/ 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "rrFragmentOperations.hpp" 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "tcuVectorUtil.hpp" 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "tcuTextureUtil.hpp" 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing tcu::IVec2; 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing tcu::Vec3; 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing tcu::Vec4; 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing tcu::IVec4; 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing tcu::UVec4; 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing tcu::min; 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing tcu::max; 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing tcu::clamp; 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing de::min; 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing de::max; 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing de::clamp; 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace rr 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Return oldValue with the bits indicated by mask replaced by corresponding bits of newValue. 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic inline int maskedBitReplace (int oldValue, int newValue, deUint32 mask) 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (oldValue & ~mask) | (newValue & mask); 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic inline bool isInsideRect (const IVec2& point, const WindowRectangle& rect) 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return de::inBounds(point.x(), rect.left, rect.left + rect.width) && 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org de::inBounds(point.y(), rect.bottom, rect.bottom + rect.height); 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic inline Vec4 unpremultiply (const Vec4& v) 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (v.w() > 0.0f) 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Vec4(v.x()/v.w(), v.y()/v.w(), v.z()/v.w(), v.w()); 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_ASSERT(v.x() == 0.0f && v.y() == 0.0f && v.z() == 0.0f); 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Vec4(0.0f, 0.0f, 0.0f, 0.0f); 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid clearMultisampleColorBuffer (const tcu::PixelBufferAccess& dst, const Vec4& v, const WindowRectangle& r) { tcu::clear(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v); } 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid clearMultisampleColorBuffer (const tcu::PixelBufferAccess& dst, const IVec4& v, const WindowRectangle& r) { tcu::clear(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v); } 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid clearMultisampleColorBuffer (const tcu::PixelBufferAccess& dst, const UVec4& v, const WindowRectangle& r) { tcu::clear(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v.cast<int>()); } 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid clearMultisampleDepthBuffer (const tcu::PixelBufferAccess& dst, float v, const WindowRectangle& r) { tcu::clearDepth(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v); } 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid clearMultisampleStencilBuffer (const tcu::PixelBufferAccess& dst, int v, const WindowRectangle& r) { tcu::clearStencil(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v); } 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgFragmentProcessor::FragmentProcessor (void) 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : m_sampleRegister() 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FragmentProcessor::executeScissorTest (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const WindowRectangle& scissorRect) 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive) 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fragNdx = fragNdxOffset + regSampleNdx/numSamplesPerFragment; 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!isInsideRect(inputFragments[fragNdx].pixelCoord, scissorRect)) 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org m_sampleRegister[regSampleNdx].isAlive = false; 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FragmentProcessor::executeStencilCompare (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const StencilState& stencilState, int numStencilBits, const tcu::ConstPixelBufferAccess& stencilBuffer) 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SAMPLE_REGISTER_STENCIL_COMPARE(COMPARE_EXPRESSION) \ 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive) \ 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fragSampleNdx = regSampleNdx % numSamplesPerFragment; \ 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; \ 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); \ 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int maskedRef = stencilState.compMask & clampedStencilRef; \ 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int maskedBuf = stencilState.compMask & stencilBufferValue; \ 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(maskedRef); \ 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(maskedBuf); \ 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org m_sampleRegister[regSampleNdx].stencilPassed = (COMPARE_EXPRESSION); \ 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } \ 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int clampedStencilRef = de::clamp(stencilState.ref, 0, (1<<numStencilBits)-1); 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (stencilState.func) 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_NEVER: SAMPLE_REGISTER_STENCIL_COMPARE(false) break; 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_ALWAYS: SAMPLE_REGISTER_STENCIL_COMPARE(true) break; 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_LESS: SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef < maskedBuf) break; 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_LEQUAL: SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef <= maskedBuf) break; 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_GREATER: SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef > maskedBuf) break; 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_GEQUAL: SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef >= maskedBuf) break; 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_EQUAL: SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef == maskedBuf) break; 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_NOTEQUAL: SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef != maskedBuf) break; 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_ASSERT(false); 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef SAMPLE_REGISTER_STENCIL_COMPARE 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FragmentProcessor::executeStencilSFail (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const StencilState& stencilState, int numStencilBits, const tcu::PixelBufferAccess& stencilBuffer) 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SAMPLE_REGISTER_SFAIL(SFAIL_EXPRESSION) \ 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive && !m_sampleRegister[regSampleNdx].stencilPassed) \ 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fragSampleNdx = regSampleNdx % numSamplesPerFragment; \ 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; \ 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); \ 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stencilBuffer.setPixStencil(maskedBitReplace(stencilBufferValue, (SFAIL_EXPRESSION), stencilState.writeMask), fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); \ 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org m_sampleRegister[regSampleNdx].isAlive = false; \ 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } \ 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int clampedStencilRef = de::clamp(stencilState.ref, 0, (1<<numStencilBits)-1); 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (stencilState.sFail) 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_KEEP: SAMPLE_REGISTER_SFAIL(stencilBufferValue) break; 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_ZERO: SAMPLE_REGISTER_SFAIL(0) break; 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_REPLACE: SAMPLE_REGISTER_SFAIL(clampedStencilRef) break; 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_INCR: SAMPLE_REGISTER_SFAIL(de::clamp(stencilBufferValue+1, 0, (1<<numStencilBits) - 1)) break; 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_DECR: SAMPLE_REGISTER_SFAIL(de::clamp(stencilBufferValue-1, 0, (1<<numStencilBits) - 1)) break; 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_INCR_WRAP: SAMPLE_REGISTER_SFAIL((stencilBufferValue + 1) & ((1<<numStencilBits) - 1)) break; 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_DECR_WRAP: SAMPLE_REGISTER_SFAIL((stencilBufferValue - 1) & ((1<<numStencilBits) - 1)) break; 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_INVERT: SAMPLE_REGISTER_SFAIL((~stencilBufferValue) & ((1<<numStencilBits) - 1)) break; 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_ASSERT(false); 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef SAMPLE_REGISTER_SFAIL 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FragmentProcessor::executeDepthCompare (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, TestFunc depthFunc, const tcu::ConstPixelBufferAccess& depthBuffer) 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SAMPLE_REGISTER_DEPTH_COMPARE_F(COMPARE_EXPRESSION) \ 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive) \ 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fragSampleNdx = regSampleNdx % numSamplesPerFragment; \ 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; \ 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float depthBufferValue = depthBuffer.getPixDepth(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); \ 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float sampleDepthFloat = frag.sampleDepths[fragSampleNdx]; \ 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float sampleDepth = de::clamp(sampleDepthFloat, 0.0f, 1.0f); \ 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org m_sampleRegister[regSampleNdx].depthPassed = (COMPARE_EXPRESSION); \ 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(depthBufferValue); \ 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(sampleDepth); \ 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } \ 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SAMPLE_REGISTER_DEPTH_COMPARE_UI(COMPARE_EXPRESSION) \ 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive) \ 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fragSampleNdx = regSampleNdx % numSamplesPerFragment; \ 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; \ 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org deUint32 depthBufferValue = depthBuffer.getPixelUint(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()).x(); \ 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float sampleDepthFloat = frag.sampleDepths[fragSampleNdx]; \ 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /* Convert input float to target buffer format for comparison */ \ 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org deUint32 buffer[2]; \ 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_ASSERT(sizeof(buffer) >= (size_t)depthBuffer.getFormat().getPixelSize()); \ 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tcu::PixelBufferAccess access(depthBuffer.getFormat(), 1, 1, 1, &buffer); \ 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org access.setPixDepth(sampleDepthFloat, 0, 0, 0); \ 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org deUint32 sampleDepth = access.getPixelUint(0, 0, 0).x(); \ 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org m_sampleRegister[regSampleNdx].depthPassed = (COMPARE_EXPRESSION); \ 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(depthBufferValue); \ 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(sampleDepth); \ 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } \ 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (depthBuffer.getFormat().type == tcu::TextureFormat::FLOAT || depthBuffer.getFormat().type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV) 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (depthFunc) 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_NEVER: SAMPLE_REGISTER_DEPTH_COMPARE_F(false) break; 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_ALWAYS: SAMPLE_REGISTER_DEPTH_COMPARE_F(true) break; 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_LESS: SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth < depthBufferValue) break; 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_LEQUAL: SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth <= depthBufferValue) break; 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_GREATER: SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth > depthBufferValue) break; 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_GEQUAL: SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth >= depthBufferValue) break; 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_EQUAL: SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth == depthBufferValue) break; 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_NOTEQUAL: SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth != depthBufferValue) break; 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_ASSERT(false); 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (depthFunc) 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_NEVER: SAMPLE_REGISTER_DEPTH_COMPARE_UI(false) break; 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_ALWAYS: SAMPLE_REGISTER_DEPTH_COMPARE_UI(true) break; 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_LESS: SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth < depthBufferValue) break; 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_LEQUAL: SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth <= depthBufferValue) break; 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_GREATER: SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth > depthBufferValue) break; 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_GEQUAL: SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth >= depthBufferValue) break; 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_EQUAL: SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth == depthBufferValue) break; 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case TESTFUNC_NOTEQUAL: SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth != depthBufferValue) break; 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_ASSERT(false); 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef SAMPLE_REGISTER_DEPTH_COMPARE_F 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef SAMPLE_REGISTER_DEPTH_COMPARE_UI 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FragmentProcessor::executeDepthWrite (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const tcu::PixelBufferAccess& depthBuffer) 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive && m_sampleRegister[regSampleNdx].depthPassed) 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const float clampedDepth = de::clamp(frag.sampleDepths[fragSampleNdx], 0.0f, 1.0f); 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org depthBuffer.setPixDepth(clampedDepth, fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FragmentProcessor::executeStencilDpFailAndPass (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const StencilState& stencilState, int numStencilBits, const tcu::PixelBufferAccess& stencilBuffer) 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, EXPRESSION) \ 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive && (CONDITION)) \ 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fragSampleNdx = regSampleNdx % numSamplesPerFragment; \ 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; \ 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); \ 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stencilBuffer.setPixStencil(maskedBitReplace(stencilBufferValue, (EXPRESSION), stencilState.writeMask), fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); \ 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } \ 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SWITCH_DPFAIL_OR_DPPASS(OP_NAME, CONDITION) \ 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (stencilState.OP_NAME) \ 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_KEEP: SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, stencilBufferValue) break; \ 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_ZERO: SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, 0) break; \ 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_REPLACE: SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, clampedStencilRef) break; \ 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_INCR: SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, de::clamp(stencilBufferValue+1, 0, (1<<numStencilBits) - 1)) break; \ 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_DECR: SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, de::clamp(stencilBufferValue-1, 0, (1<<numStencilBits) - 1)) break; \ 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_INCR_WRAP: SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, (stencilBufferValue + 1) & ((1<<numStencilBits) - 1)) break; \ 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_DECR_WRAP: SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, (stencilBufferValue - 1) & ((1<<numStencilBits) - 1)) break; \ 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case STENCILOP_INVERT: SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, (~stencilBufferValue) & ((1<<numStencilBits) - 1)) break; \ 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: \ 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_ASSERT(false); \ 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int clampedStencilRef = de::clamp(stencilState.ref, 0, (1<<numStencilBits)-1); 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SWITCH_DPFAIL_OR_DPPASS(dpFail, !m_sampleRegister[regSampleNdx].depthPassed) 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SWITCH_DPFAIL_OR_DPPASS(dpPass, m_sampleRegister[regSampleNdx].depthPassed) 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef SWITCH_DPFAIL_OR_DPPASS 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef SAMPLE_REGISTER_DPFAIL_OR_DPPASS 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FragmentProcessor::executeBlendFactorComputeRGB (const Vec4& blendColor, const BlendState& blendRGBState) 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, FACTOR_EXPRESSION) \ 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive) \ 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Vec4& src = m_sampleRegister[regSampleNdx].clampedBlendSrcColor; \ 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Vec4& src1 = m_sampleRegister[regSampleNdx].clampedBlendSrc1Color; \ 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Vec4& dst = m_sampleRegister[regSampleNdx].clampedBlendDstColor; \ 314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(src); \ 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(src1); \ 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(dst); \ 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org m_sampleRegister[regSampleNdx].FACTOR_NAME = clamp((FACTOR_EXPRESSION), Vec3(0.0f), Vec3(1.0f)); \ 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } \ 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SWITCH_SRC_OR_DST_FACTOR_RGB(FUNC_NAME, FACTOR_NAME) \ 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (blendRGBState.FUNC_NAME) \ 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ZERO: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(0.0f)) break; \ 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f)) break; \ 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_SRC_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src.swizzle(0,1,2)) break; \ 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE_MINUS_SRC_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f) - src.swizzle(0,1,2)) break; \ 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_DST_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, dst.swizzle(0,1,2)) break; \ 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE_MINUS_DST_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f) - dst.swizzle(0,1,2)) break; \ 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_SRC_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(src.w())) break; \ 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE_MINUS_SRC_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f - src.w())) break; \ 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_DST_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(dst.w())) break; \ 334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE_MINUS_DST_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f - dst.w())) break; \ 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_CONSTANT_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, blendColor.swizzle(0,1,2)) break; \ 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE_MINUS_CONSTANT_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f) - blendColor.swizzle(0,1,2)) break; \ 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_CONSTANT_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(blendColor.w())) break; \ 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE_MINUS_CONSTANT_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f - blendColor.w())) break; \ 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_SRC_ALPHA_SATURATE: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(de::min(src.w(), 1.0f - dst.w()))) break; \ 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_SRC1_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src1.swizzle(0,1,2)) break; \ 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE_MINUS_SRC1_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f) - src1.swizzle(0,1,2)) break; \ 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_SRC1_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(src1.w())) break; \ 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case BLENDFUNC_ONE_MINUS_SRC1_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f - src1.w())) break; \ 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: \ 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_ASSERT(false); \ 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SWITCH_SRC_OR_DST_FACTOR_RGB(srcFunc, blendSrcFactorRGB) 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org SWITCH_SRC_OR_DST_FACTOR_RGB(dstFunc, blendDstFactorRGB) 350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef SWITCH_SRC_OR_DST_FACTOR_RGB 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#undef SAMPLE_REGISTER_BLEND_FACTOR 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FragmentProcessor::executeBlendFactorComputeA (const Vec4& blendColor, const BlendState& blendAState) 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, FACTOR_EXPRESSION) \ 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (m_sampleRegister[regSampleNdx].isAlive) \ 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { \ 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Vec4& src = m_sampleRegister[regSampleNdx].clampedBlendSrcColor; \ 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Vec4& src1 = m_sampleRegister[regSampleNdx].clampedBlendSrc1Color; \ 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const Vec4& dst = m_sampleRegister[regSampleNdx].clampedBlendDstColor; \ 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(src); \ 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(src1); \ 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DE_UNREF(dst); \ 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org \ 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org m_sampleRegister[regSampleNdx].FACTOR_NAME = clamp((FACTOR_EXPRESSION), 0.0f, 1.0f); \ 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } \ 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3733b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org#define SWITCH_SRC_OR_DST_FACTOR_A(FUNC_NAME, FACTOR_NAME) \ 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (blendAState.FUNC_NAME) \ 375 { \ 376 case BLENDFUNC_ZERO: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 0.0f) break; \ 377 case BLENDFUNC_ONE: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f) break; \ 378 case BLENDFUNC_SRC_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src.w()) break; \ 379 case BLENDFUNC_ONE_MINUS_SRC_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - src.w()) break; \ 380 case BLENDFUNC_DST_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, dst.w()) break; \ 381 case BLENDFUNC_ONE_MINUS_DST_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - dst.w()) break; \ 382 case BLENDFUNC_SRC_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src.w()) break; \ 383 case BLENDFUNC_ONE_MINUS_SRC_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - src.w()) break; \ 384 case BLENDFUNC_DST_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, dst.w()) break; \ 385 case BLENDFUNC_ONE_MINUS_DST_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - dst.w()) break; \ 386 case BLENDFUNC_CONSTANT_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, blendColor.w()) break; \ 387 case BLENDFUNC_ONE_MINUS_CONSTANT_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - blendColor.w()) break; \ 388 case BLENDFUNC_CONSTANT_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, blendColor.w()) break; \ 389 case BLENDFUNC_ONE_MINUS_CONSTANT_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - blendColor.w()) break; \ 390 case BLENDFUNC_SRC_ALPHA_SATURATE: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f) break; \ 391 case BLENDFUNC_SRC1_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src1.w()) break; \ 392 case BLENDFUNC_ONE_MINUS_SRC1_COLOR: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - src1.w()) break; \ 393 case BLENDFUNC_SRC1_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src1.w()) break; \ 394 case BLENDFUNC_ONE_MINUS_SRC1_ALPHA: SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - src1.w()) break; \ 395 default: \ 396 DE_ASSERT(false); \ 397 } 398 399 SWITCH_SRC_OR_DST_FACTOR_A(srcFunc, blendSrcFactorA) 400 SWITCH_SRC_OR_DST_FACTOR_A(dstFunc, blendDstFactorA) 401 402#undef SWITCH_SRC_OR_DST_FACTOR_A 403#undef SAMPLE_REGISTER_BLEND_FACTOR 404} 405 406void FragmentProcessor::executeBlend (const BlendState& blendRGBState, const BlendState& blendAState) 407{ 408#define SAMPLE_REGISTER_BLENDED_COLOR(COLOR_NAME, COLOR_EXPRESSION) \ 409 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 410 { \ 411 if (m_sampleRegister[regSampleNdx].isAlive) \ 412 { \ 413 SampleData& sample = m_sampleRegister[regSampleNdx]; \ 414 const Vec4& srcColor = sample.clampedBlendSrcColor; \ 415 const Vec4& dstColor = sample.clampedBlendDstColor; \ 416 \ 417 sample.COLOR_NAME = (COLOR_EXPRESSION); \ 418 } \ 419 } 420 421 switch (blendRGBState.equation) 422 { 423 case BLENDEQUATION_ADD: SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, srcColor.swizzle(0,1,2)*sample.blendSrcFactorRGB + dstColor.swizzle(0,1,2)*sample.blendDstFactorRGB) break; 424 case BLENDEQUATION_SUBTRACT: SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, srcColor.swizzle(0,1,2)*sample.blendSrcFactorRGB - dstColor.swizzle(0,1,2)*sample.blendDstFactorRGB) break; 425 case BLENDEQUATION_REVERSE_SUBTRACT: SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, dstColor.swizzle(0,1,2)*sample.blendDstFactorRGB - srcColor.swizzle(0,1,2)*sample.blendSrcFactorRGB) break; 426 case BLENDEQUATION_MIN: SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, min(srcColor.swizzle(0,1,2), dstColor.swizzle(0,1,2))) break; 427 case BLENDEQUATION_MAX: SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, max(srcColor.swizzle(0,1,2), dstColor.swizzle(0,1,2))) break; 428 default: 429 DE_ASSERT(false); 430 } 431 432 switch (blendAState.equation) 433 { 434 case BLENDEQUATION_ADD: SAMPLE_REGISTER_BLENDED_COLOR(blendedA, srcColor.w()*sample.blendSrcFactorA + dstColor.w()*sample.blendDstFactorA) break; 435 case BLENDEQUATION_SUBTRACT: SAMPLE_REGISTER_BLENDED_COLOR(blendedA, srcColor.w()*sample.blendSrcFactorA - dstColor.w()*sample.blendDstFactorA) break; 436 case BLENDEQUATION_REVERSE_SUBTRACT: SAMPLE_REGISTER_BLENDED_COLOR(blendedA, dstColor.w()*sample.blendDstFactorA - srcColor.w()*sample.blendSrcFactorA) break; 437 case BLENDEQUATION_MIN: SAMPLE_REGISTER_BLENDED_COLOR(blendedA, min(srcColor.w(), dstColor.w())) break; 438 case BLENDEQUATION_MAX: SAMPLE_REGISTER_BLENDED_COLOR(blendedA, max(srcColor.w(), dstColor.w())) break; 439 default: 440 DE_ASSERT(false); 441 } 442#undef SAMPLE_REGISTER_BLENDED_COLOR 443} 444 445namespace advblend 446{ 447 448inline float multiply (float src, float dst) { return src*dst; } 449inline float screen (float src, float dst) { return src + dst - src*dst; } 450inline float darken (float src, float dst) { return de::min(src, dst); } 451inline float lighten (float src, float dst) { return de::max(src, dst); } 452inline float difference (float src, float dst) { return de::abs(dst-src); } 453inline float exclusion (float src, float dst) { return src + dst - 2.0f*src*dst; } 454 455inline float overlay (float src, float dst) 456{ 457 if (dst <= 0.5f) 458 return 2.0f*src*dst; 459 else 460 return 1.0f - 2.0f*(1.0f-src)*(1.0f-dst); 461} 462 463inline float colordodge (float src, float dst) 464{ 465 if (dst <= 0.0f) 466 return 0.0f; 467 else if (src < 1.0f) 468 return de::min(1.0f, dst/(1.0f-src)); 469 else 470 return 1.0f; 471} 472 473inline float colorburn (float src, float dst) 474{ 475 if (dst >= 1.0f) 476 return 1.0f; 477 else if (src > 0.0f) 478 return 1.0f - de::min(1.0f, (1.0f-dst)/src); 479 else 480 return 0.0f; 481} 482 483inline float hardlight (float src, float dst) 484{ 485 if (src <= 0.5f) 486 return 2.0f*src*dst; 487 else 488 return 1.0f - 2.0f*(1.0f-src)*(1.0f-dst); 489} 490 491inline float softlight (float src, float dst) 492{ 493 if (src <= 0.5f) 494 return dst - (1.0f - 2.0f*src)*dst*(1.0f-dst); 495 else if (dst <= 0.25f) 496 return dst + (2.0f*src - 1.0f)*dst*((16.0f*dst - 12.0f)*dst + 3.0f); 497 else 498 return dst + (2.0f*src - 1.0f)*(deFloatSqrt(dst)-dst); 499} 500 501inline float minComp (const Vec3& v) 502{ 503 return de::min(de::min(v.x(), v.y()), v.z()); 504} 505 506inline float maxComp (const Vec3& v) 507{ 508 return de::max(de::max(v.x(), v.y()), v.z()); 509} 510 511inline float luminosity (const Vec3& rgb) 512{ 513 return dot(rgb, Vec3(0.3f, 0.59f, 0.11f)); 514} 515 516inline float saturation (const Vec3& rgb) 517{ 518 return maxComp(rgb) - minComp(rgb); 519} 520 521Vec3 setLum (const Vec3& cbase, const Vec3& clum) 522{ 523 const float lbase = luminosity(cbase); 524 const float llum = luminosity(clum); 525 const float ldiff = llum - lbase; 526 const Vec3 color = cbase + Vec3(ldiff); 527 const float minC = minComp(color); 528 const float maxC = maxComp(color); 529 530 if (minC < 0.0f) 531 return llum + ((color-llum)*llum / (llum != minC ? (llum-minC) : 1.0f)); 532 else if (maxC > 1.0f) 533 return llum + ((color-llum)*(1.0f-llum) / (llum != maxC ? (maxC-llum) : 1.0f)); 534 else 535 return color; 536} 537 538Vec3 setLumSat (const Vec3& cbase, const Vec3& csat, const Vec3& clum) 539{ 540 const float minbase = minComp(cbase); 541 const float sbase = saturation(cbase); 542 const float ssat = saturation(csat); 543 Vec3 color = Vec3(0.0f); 544 545 if (sbase > 0.0f) 546 color = (cbase - minbase) * ssat / sbase; 547 else 548 color = color; 549 550 return setLum(color, clum); 551} 552 553} // advblend 554 555void FragmentProcessor::executeAdvancedBlend (BlendEquationAdvanced equation) 556{ 557 using namespace advblend; 558 559#define SAMPLE_REGISTER_ADV_BLEND(FUNCTION_NAME) \ 560 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 561 { \ 562 if (m_sampleRegister[regSampleNdx].isAlive) \ 563 { \ 564 SampleData& sample = m_sampleRegister[regSampleNdx]; \ 565 const Vec4& srcColor = sample.clampedBlendSrcColor; \ 566 const Vec4& dstColor = sample.clampedBlendDstColor; \ 567 const Vec3& bias = sample.blendSrcFactorRGB; \ 568 const float p0 = sample.blendSrcFactorA; \ 569 const float r = FUNCTION_NAME(srcColor[0], dstColor[0])*p0 + bias[0]; \ 570 const float g = FUNCTION_NAME(srcColor[1], dstColor[1])*p0 + bias[1]; \ 571 const float b = FUNCTION_NAME(srcColor[2], dstColor[2])*p0 + bias[2]; \ 572 \ 573 sample.blendedRGB = Vec3(r, g, b); \ 574 } \ 575 } 576 577#define SAMPLE_REGISTER_ADV_BLEND_HSL(COLOR_EXPRESSION) \ 578 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \ 579 { \ 580 if (m_sampleRegister[regSampleNdx].isAlive) \ 581 { \ 582 SampleData& sample = m_sampleRegister[regSampleNdx]; \ 583 const Vec3 srcColor = sample.clampedBlendSrcColor.swizzle(0,1,2); \ 584 const Vec3 dstColor = sample.clampedBlendDstColor.swizzle(0,1,2); \ 585 const Vec3& bias = sample.blendSrcFactorRGB; \ 586 const float p0 = sample.blendSrcFactorA; \ 587 \ 588 sample.blendedRGB = (COLOR_EXPRESSION)*p0 + bias; \ 589 } \ 590 } 591 592 // Pre-compute factors & compute alpha \todo [2014-03-18 pyry] Re-using variable names. 593 // \note clampedBlend*Color contains clamped & unpremultiplied colors 594 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 595 { 596 if (m_sampleRegister[regSampleNdx].isAlive) 597 { 598 SampleData& sample = m_sampleRegister[regSampleNdx]; 599 const Vec4& srcColor = sample.clampedBlendSrcColor; 600 const Vec4& dstColor = sample.clampedBlendDstColor; 601 const float srcA = srcColor.w(); 602 const float dstA = dstColor.w(); 603 const float p0 = srcA*dstA; 604 const float p1 = srcA*(1.0f-dstA); 605 const float p2 = dstA*(1.0f-srcA); 606 const Vec3 bias (srcColor[0]*p1 + dstColor[0]*p2, 607 srcColor[1]*p1 + dstColor[1]*p2, 608 srcColor[2]*p1 + dstColor[2]*p2); 609 610 sample.blendSrcFactorRGB = bias; 611 sample.blendSrcFactorA = p0; 612 sample.blendedA = p0 + p1 + p2; 613 } 614 } 615 616 switch (equation) 617 { 618 case BLENDEQUATION_ADVANCED_MULTIPLY: SAMPLE_REGISTER_ADV_BLEND(multiply); break; 619 case BLENDEQUATION_ADVANCED_SCREEN: SAMPLE_REGISTER_ADV_BLEND(screen); break; 620 case BLENDEQUATION_ADVANCED_OVERLAY: SAMPLE_REGISTER_ADV_BLEND(overlay); break; 621 case BLENDEQUATION_ADVANCED_DARKEN: SAMPLE_REGISTER_ADV_BLEND(darken); break; 622 case BLENDEQUATION_ADVANCED_LIGHTEN: SAMPLE_REGISTER_ADV_BLEND(lighten); break; 623 case BLENDEQUATION_ADVANCED_COLORDODGE: SAMPLE_REGISTER_ADV_BLEND(colordodge); break; 624 case BLENDEQUATION_ADVANCED_COLORBURN: SAMPLE_REGISTER_ADV_BLEND(colorburn); break; 625 case BLENDEQUATION_ADVANCED_HARDLIGHT: SAMPLE_REGISTER_ADV_BLEND(hardlight); break; 626 case BLENDEQUATION_ADVANCED_SOFTLIGHT: SAMPLE_REGISTER_ADV_BLEND(softlight); break; 627 case BLENDEQUATION_ADVANCED_DIFFERENCE: SAMPLE_REGISTER_ADV_BLEND(difference); break; 628 case BLENDEQUATION_ADVANCED_EXCLUSION: SAMPLE_REGISTER_ADV_BLEND(exclusion); break; 629 case BLENDEQUATION_ADVANCED_HSL_HUE: SAMPLE_REGISTER_ADV_BLEND_HSL(setLumSat(srcColor, dstColor, dstColor)); break; 630 case BLENDEQUATION_ADVANCED_HSL_SATURATION: SAMPLE_REGISTER_ADV_BLEND_HSL(setLumSat(dstColor, srcColor, dstColor)); break; 631 case BLENDEQUATION_ADVANCED_HSL_COLOR: SAMPLE_REGISTER_ADV_BLEND_HSL(setLum(srcColor, dstColor)); break; 632 case BLENDEQUATION_ADVANCED_HSL_LUMINOSITY: SAMPLE_REGISTER_ADV_BLEND_HSL(setLum(dstColor, srcColor)); break; 633 default: 634 DE_ASSERT(false); 635 } 636 637#undef SAMPLE_REGISTER_ADV_BLEND 638#undef SAMPLE_REGISTER_ADV_BLEND_HSL 639} 640 641void FragmentProcessor::executeColorWrite (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, bool isSRGB, const tcu::PixelBufferAccess& colorBuffer) 642{ 643 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 644 { 645 if (m_sampleRegister[regSampleNdx].isAlive) 646 { 647 int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 648 const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; 649 Vec4 combinedColor; 650 651 combinedColor.xyz() = m_sampleRegister[regSampleNdx].blendedRGB; 652 combinedColor.w() = m_sampleRegister[regSampleNdx].blendedA; 653 654 if (isSRGB) 655 combinedColor = tcu::linearToSRGB(combinedColor); 656 657 colorBuffer.setPixel(combinedColor, fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 658 } 659 } 660} 661 662void FragmentProcessor::executeRGBA8ColorWrite (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const tcu::PixelBufferAccess& colorBuffer) 663{ 664 const int fragStride = 4; 665 const int xStride = colorBuffer.getRowPitch(); 666 const int yStride = colorBuffer.getSlicePitch(); 667 deUint8* const basePtr = (deUint8*)colorBuffer.getDataPtr(); 668 669 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 670 { 671 if (m_sampleRegister[regSampleNdx].isAlive) 672 { 673 const int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 674 const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; 675 Vec4 combinedColor; 676 deUint8* dstPtr = basePtr + fragSampleNdx*fragStride + frag.pixelCoord.x()*xStride + frag.pixelCoord.y()*yStride; 677 678 dstPtr[0] = tcu::floatToU8(m_sampleRegister[regSampleNdx].blendedRGB.x()); 679 dstPtr[1] = tcu::floatToU8(m_sampleRegister[regSampleNdx].blendedRGB.y()); 680 dstPtr[2] = tcu::floatToU8(m_sampleRegister[regSampleNdx].blendedRGB.z()); 681 dstPtr[3] = tcu::floatToU8(m_sampleRegister[regSampleNdx].blendedA); 682 } 683 } 684} 685 686void FragmentProcessor::executeMaskedColorWrite (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const Vec4& colorMaskFactor, const Vec4& colorMaskNegationFactor, bool isSRGB, const tcu::PixelBufferAccess& colorBuffer) 687{ 688 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 689 { 690 if (m_sampleRegister[regSampleNdx].isAlive) 691 { 692 int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 693 const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; 694 Vec4 originalColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 695 Vec4 newColor; 696 697 newColor.xyz() = m_sampleRegister[regSampleNdx].blendedRGB; 698 newColor.w() = m_sampleRegister[regSampleNdx].blendedA; 699 700 if (isSRGB) 701 newColor = tcu::linearToSRGB(newColor); 702 703 newColor = colorMaskFactor*newColor + colorMaskNegationFactor*originalColor; 704 705 colorBuffer.setPixel(newColor, fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 706 } 707 } 708} 709 710void FragmentProcessor::executeSignedValueWrite (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const tcu::BVec4& colorMask, const tcu::PixelBufferAccess& colorBuffer) 711{ 712 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 713 { 714 if (m_sampleRegister[regSampleNdx].isAlive) 715 { 716 int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 717 const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; 718 const IVec4 originalValue = colorBuffer.getPixelInt(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 719 720 colorBuffer.setPixel(tcu::select(m_sampleRegister[regSampleNdx].signedValue, originalValue, colorMask), fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 721 } 722 } 723} 724 725void FragmentProcessor::executeUnsignedValueWrite (int fragNdxOffset, int numSamplesPerFragment, const Fragment* inputFragments, const tcu::BVec4& colorMask, const tcu::PixelBufferAccess& colorBuffer) 726{ 727 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 728 { 729 if (m_sampleRegister[regSampleNdx].isAlive) 730 { 731 int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 732 const Fragment& frag = inputFragments[fragNdxOffset + regSampleNdx/numSamplesPerFragment]; 733 const UVec4 originalValue = colorBuffer.getPixelUint(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 734 735 colorBuffer.setPixel(tcu::select(m_sampleRegister[regSampleNdx].unsignedValue, originalValue, colorMask), fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 736 } 737 } 738} 739 740void FragmentProcessor::render (const rr::MultisamplePixelBufferAccess& msColorBuffer, 741 const rr::MultisamplePixelBufferAccess& msDepthBuffer, 742 const rr::MultisamplePixelBufferAccess& msStencilBuffer, 743 const Fragment* inputFragments, 744 int numFragments, 745 FaceType fragmentFacing, 746 const FragmentOperationState& state) 747{ 748 DE_ASSERT(fragmentFacing < FACETYPE_LAST); 749 750 const tcu::PixelBufferAccess& colorBuffer = msColorBuffer.raw(); 751 const tcu::PixelBufferAccess& depthBuffer = msDepthBuffer.raw(); 752 const tcu::PixelBufferAccess& stencilBuffer = msStencilBuffer.raw(); 753 754 bool hasDepth = depthBuffer.getWidth() > 0 && depthBuffer.getHeight() > 0 && depthBuffer.getDepth() > 0; 755 bool hasStencil = stencilBuffer.getWidth() > 0 && stencilBuffer.getHeight() > 0 && stencilBuffer.getDepth() > 0; 756 bool doDepthTest = hasDepth && state.depthTestEnabled; 757 bool doStencilTest = hasStencil && state.stencilTestEnabled; 758 759 tcu::TextureChannelClass colorbufferClass = tcu::getTextureChannelClass(msColorBuffer.raw().getFormat().type); 760 rr::GenericVecType fragmentDataType = (colorbufferClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ? (rr::GENERICVECTYPE_INT32) : ((colorbufferClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (rr::GENERICVECTYPE_UINT32) : (rr::GENERICVECTYPE_FLOAT)); 761 762 DE_ASSERT((!hasDepth || colorBuffer.getWidth() == depthBuffer.getWidth()) && (!hasStencil || colorBuffer.getWidth() == stencilBuffer.getWidth())); 763 DE_ASSERT((!hasDepth || colorBuffer.getHeight() == depthBuffer.getHeight()) && (!hasStencil || colorBuffer.getHeight() == stencilBuffer.getHeight())); 764 DE_ASSERT((!hasDepth || colorBuffer.getDepth() == depthBuffer.getDepth()) && (!hasStencil || colorBuffer.getDepth() == stencilBuffer.getDepth())); 765 766 int numSamplesPerFragment = colorBuffer.getWidth(); 767 int totalNumSamples = numFragments*numSamplesPerFragment; 768 int numSampleGroups = (totalNumSamples - 1) / SAMPLE_REGISTER_SIZE + 1; // \note totalNumSamples/SAMPLE_REGISTER_SIZE rounded up. 769 const StencilState& stencilState = state.stencilStates[fragmentFacing]; 770 Vec4 colorMaskFactor (state.colorMask[0] ? 1.0f : 0.0f, state.colorMask[1] ? 1.0f : 0.0f, state.colorMask[2] ? 1.0f : 0.0f, state.colorMask[3] ? 1.0f : 0.0f); 771 Vec4 colorMaskNegationFactor (state.colorMask[0] ? 0.0f : 1.0f, state.colorMask[1] ? 0.0f : 1.0f, state.colorMask[2] ? 0.0f : 1.0f, state.colorMask[3] ? 0.0f : 1.0f); 772 bool sRGBTarget = state.sRGBEnabled && (colorBuffer.getFormat().order == tcu::TextureFormat::sRGBA || 773 colorBuffer.getFormat().order == tcu::TextureFormat::sRGB); 774 775 DE_ASSERT(SAMPLE_REGISTER_SIZE % numSamplesPerFragment == 0); 776 777 // Divide the fragments' samples into groups of size SAMPLE_REGISTER_SIZE, and perform 778 // the per-sample operations for one group at a time. 779 780 for (int sampleGroupNdx = 0; sampleGroupNdx < numSampleGroups; sampleGroupNdx++) 781 { 782 // The index of the fragment of the sample at the beginning of m_sampleRegisters. 783 int groupFirstFragNdx = (sampleGroupNdx*SAMPLE_REGISTER_SIZE) / numSamplesPerFragment; 784 785 // Initialize sample data in the sample register. 786 787 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 788 { 789 int fragNdx = groupFirstFragNdx + regSampleNdx/numSamplesPerFragment; 790 int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 791 792 if (fragNdx < numFragments) 793 { 794 m_sampleRegister[regSampleNdx].isAlive = (inputFragments[fragNdx].coverage & (1u << fragSampleNdx)) != 0; 795 m_sampleRegister[regSampleNdx].depthPassed = true; // \note This will stay true if depth test is disabled. 796 } 797 else 798 m_sampleRegister[regSampleNdx].isAlive = false; 799 } 800 801 // Scissor test. 802 803 if (state.scissorTestEnabled) 804 executeScissorTest(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.scissorRectangle); 805 806 // Stencil test. 807 808 if (doStencilTest) 809 { 810 executeStencilCompare(groupFirstFragNdx, numSamplesPerFragment, inputFragments, stencilState, state.numStencilBits, stencilBuffer); 811 executeStencilSFail(groupFirstFragNdx, numSamplesPerFragment, inputFragments, stencilState, state.numStencilBits, stencilBuffer); 812 } 813 814 // Depth test. 815 // \note Current value of isAlive is needed for dpPass and dpFail, so it's only updated after them and not right after depth test. 816 817 if (doDepthTest) 818 { 819 executeDepthCompare(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.depthFunc, depthBuffer); 820 821 if (state.depthMask) 822 executeDepthWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, depthBuffer); 823 } 824 825 // Do dpFail and dpPass stencil writes. 826 827 if (doStencilTest) 828 executeStencilDpFailAndPass(groupFirstFragNdx, numSamplesPerFragment, inputFragments, stencilState, state.numStencilBits, stencilBuffer); 829 830 // Kill the samples that failed depth test. 831 832 if (doDepthTest) 833 { 834 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 835 m_sampleRegister[regSampleNdx].isAlive = m_sampleRegister[regSampleNdx].isAlive && m_sampleRegister[regSampleNdx].depthPassed; 836 } 837 838 // Paint fragments to target 839 840 switch (fragmentDataType) 841 { 842 case rr::GENERICVECTYPE_FLOAT: 843 // Blend calculation - only if using blend. 844 if (state.blendMode == BLENDMODE_STANDARD) 845 { 846 // Put dst color to register, doing srgb-to-linear conversion if needed. 847 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 848 { 849 if (m_sampleRegister[regSampleNdx].isAlive) 850 { 851 int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 852 const Fragment& frag = inputFragments[groupFirstFragNdx + regSampleNdx/numSamplesPerFragment]; 853 Vec4 dstColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 854 855 m_sampleRegister[regSampleNdx].clampedBlendSrcColor = clamp(frag.value.get<float>(), Vec4(0.0f), Vec4(1.0f)); 856 m_sampleRegister[regSampleNdx].clampedBlendSrc1Color = clamp(frag.value1.get<float>(), Vec4(0.0f), Vec4(1.0f)); 857 m_sampleRegister[regSampleNdx].clampedBlendDstColor = clamp(sRGBTarget ? tcu::sRGBToLinear(dstColor) : dstColor, Vec4(0.0f), Vec4(1.0f)); 858 } 859 } 860 861 // Calculate blend factors to register. 862 executeBlendFactorComputeRGB(state.blendColor, state.blendRGBState); 863 executeBlendFactorComputeA(state.blendColor, state.blendAState); 864 865 // Compute blended color. 866 executeBlend(state.blendRGBState, state.blendAState); 867 } 868 else if (state.blendMode == BLENDMODE_ADVANCED) 869 { 870 // Unpremultiply colors for blending, and do sRGB->linear if necessary 871 // \todo [2014-03-17 pyry] Re-consider clampedBlend*Color var names 872 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 873 { 874 if (m_sampleRegister[regSampleNdx].isAlive) 875 { 876 int fragSampleNdx = regSampleNdx % numSamplesPerFragment; 877 const Fragment& frag = inputFragments[groupFirstFragNdx + regSampleNdx/numSamplesPerFragment]; 878 const Vec4 srcColor = frag.value.get<float>(); 879 const Vec4 dstColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); 880 881 m_sampleRegister[regSampleNdx].clampedBlendSrcColor = unpremultiply(clamp(srcColor, Vec4(0.0f), Vec4(1.0f))); 882 m_sampleRegister[regSampleNdx].clampedBlendDstColor = unpremultiply(clamp(sRGBTarget ? tcu::sRGBToLinear(dstColor) : dstColor, Vec4(0.0f), Vec4(1.0f))); 883 } 884 } 885 886 executeAdvancedBlend(state.blendEquationAdvaced); 887 } 888 else 889 { 890 // Not using blend - just put values to register as-is. 891 DE_ASSERT(state.blendMode == BLENDMODE_NONE); 892 893 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 894 { 895 if (m_sampleRegister[regSampleNdx].isAlive) 896 { 897 const Fragment& frag = inputFragments[groupFirstFragNdx + regSampleNdx/numSamplesPerFragment]; 898 899 m_sampleRegister[regSampleNdx].blendedRGB = frag.value.get<float>().xyz(); 900 m_sampleRegister[regSampleNdx].blendedA = frag.value.get<float>().w(); 901 } 902 } 903 } 904 905 // Finally, write the colors to the color buffer. 906 907 if (state.colorMask[0] && state.colorMask[1] && state.colorMask[2] && state.colorMask[3]) 908 { 909 if (colorBuffer.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)) 910 executeRGBA8ColorWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, colorBuffer); 911 else 912 executeColorWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, sRGBTarget, colorBuffer); 913 } 914 else if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3]) 915 executeMaskedColorWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, colorMaskFactor, colorMaskNegationFactor, sRGBTarget, colorBuffer); 916 break; 917 918 case rr::GENERICVECTYPE_INT32: 919 // Write fragments 920 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 921 { 922 if (m_sampleRegister[regSampleNdx].isAlive) 923 { 924 const Fragment& frag = inputFragments[groupFirstFragNdx + regSampleNdx/numSamplesPerFragment]; 925 926 m_sampleRegister[regSampleNdx].signedValue = frag.value.get<deInt32>(); 927 } 928 } 929 930 if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3]) 931 executeSignedValueWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.colorMask, colorBuffer); 932 break; 933 934 case rr::GENERICVECTYPE_UINT32: 935 // Write fragments 936 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) 937 { 938 if (m_sampleRegister[regSampleNdx].isAlive) 939 { 940 const Fragment& frag = inputFragments[groupFirstFragNdx + regSampleNdx/numSamplesPerFragment]; 941 942 m_sampleRegister[regSampleNdx].unsignedValue = frag.value.get<deUint32>(); 943 } 944 } 945 946 if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3]) 947 executeUnsignedValueWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.colorMask, colorBuffer); 948 break; 949 950 default: 951 DE_ASSERT(DE_FALSE); 952 } 953 } 954} 955 956} // rr 957