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