#ifndef _RRRASTERIZER_HPP #define _RRRASTERIZER_HPP /*------------------------------------------------------------------------- * drawElements Quality Program Reference Renderer * ----------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Reference rasterizer *//*--------------------------------------------------------------------*/ #include "rrDefs.hpp" #include "tcuVector.hpp" #include "rrRenderState.hpp" #include "rrFragmentPacket.hpp" namespace rr { //! Rasterizer configuration enum { RASTERIZER_SUBPIXEL_BITS = 8, RASTERIZER_MAX_SAMPLES_PER_FRAGMENT = 16 }; //! Get coverage bit value. inline deUint64 getCoverageBit (int numSamples, int x, int y, int sampleNdx) { const int numBits = (int)sizeof(deUint64)*8; const int maxSamples = numBits/4; DE_STATIC_ASSERT(maxSamples >= RASTERIZER_MAX_SAMPLES_PER_FRAGMENT); DE_ASSERT(de::inRange(numSamples, 1, maxSamples) && de::inBounds(x, 0, 2) && de::inBounds(y, 0, 2)); return 1ull << ((x*2 + y)*numSamples + sampleNdx); } //! Get all sample bits for fragment inline deUint64 getCoverageFragmentSampleBits (int numSamples, int x, int y) { DE_ASSERT(de::inBounds(x, 0, 2) && de::inBounds(y, 0, 2)); const deUint64 fragMask = (1ull << numSamples) - 1; return fragMask << (x*2 + y)*numSamples; } //! Set bit in coverage mask. inline deUint64 setCoverageValue (deUint64 mask, int numSamples, int x, int y, int sampleNdx, bool val) { const deUint64 bit = getCoverageBit(numSamples, x, y, sampleNdx); return val ? (mask | bit) : (mask & ~bit); } //! Get coverage bit value in mask. inline bool getCoverageValue (deUint64 mask, int numSamples, int x, int y, int sampleNdx) { return (mask & getCoverageBit(numSamples, x, y, sampleNdx)) != 0; } //! Test if any sample for fragment is live inline bool getCoverageAnyFragmentSampleLive (deUint64 mask, int numSamples, int x, int y) { return (mask & getCoverageFragmentSampleBits(numSamples, x, y)) != 0; } //! Get position of first coverage bit of fragment - equivalent to deClz64(getCoverageFragmentSampleBits(numSamples, x, y)). inline int getCoverageOffset (int numSamples, int x, int y) { return (x*2 + y)*numSamples; } /*--------------------------------------------------------------------*//*! * \brief Edge function * * Edge function can be evaluated for point P (in fixed-point coordinates * with SUBPIXEL_BITS fractional part) by computing * D = a*Px + b*Py + c * * D will be fixed-point value where lower (SUBPIXEL_BITS*2) bits will * be fractional part. * * a and b are stored with SUBPIXEL_BITS fractional part, while c is stored * with SUBPIXEL_BITS*2 fractional bits. *//*--------------------------------------------------------------------*/ struct EdgeFunction { inline EdgeFunction (void) : a(0), b(0), c(0), inclusive(false) {} deInt64 a; deInt64 b; deInt64 c; bool inclusive; //!< True if edge is inclusive according to fill rules. }; /*--------------------------------------------------------------------*//*! * \brief Triangle rasterizer * * Triangle rasterizer implements following features: * - Rasterization using fixed-point coordinates * - 1, 4, and 16 -sample rasterization * - Depth interpolation * - Perspective-correct barycentric computation for interpolation * - Visible face determination * * It does not (and will not) implement following: * - Triangle setup * - Clipping * - Degenerate elimination * - Coordinate transformation (inputs are in screen-space) * - Culling - logic can be implemented outside by querying visible face * - Scissoring (this can be done by controlling viewport rectangle) * - Any per-fragment operations *//*--------------------------------------------------------------------*/ class TriangleRasterizer { public: TriangleRasterizer (const tcu::IVec4& viewport, const int numSamples, const RasterizationState& state); void init (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2); // Following functions are only available after init() FaceType getVisibleFace (void) const { return m_face; } void rasterize (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized); private: void rasterizeSingleSample (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized); template void rasterizeMultiSample (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized); // Constant rasterization state. const tcu::IVec4 m_viewport; const int m_numSamples; const Winding m_winding; const HorizontalFill m_horizontalFill; const VerticalFill m_verticalFill; // Per-triangle rasterization state. tcu::Vec4 m_v0; tcu::Vec4 m_v1; tcu::Vec4 m_v2; EdgeFunction m_edge01; EdgeFunction m_edge12; EdgeFunction m_edge20; FaceType m_face; //!< Triangle orientation, eg. visible face. tcu::IVec2 m_bboxMin; //!< Bounding box min (inclusive). tcu::IVec2 m_bboxMax; //!< Bounding box max (inclusive). tcu::IVec2 m_curPos; //!< Current rasterization position. ViewportOrientation m_viewportOrientation; //!< Direction of +x+y axis } DE_WARN_UNUSED_TYPE; /*--------------------------------------------------------------------*//*! * \brief Single sample line rasterizer * * Line rasterizer implements following features: * - Rasterization using fixed-point coordinates * - Depth interpolation * - Perspective-correct interpolation * * It does not (and will not) implement following: * - Clipping * - Multisampled line rasterization *//*--------------------------------------------------------------------*/ class SingleSampleLineRasterizer { public: SingleSampleLineRasterizer (const tcu::IVec4& viewport); ~SingleSampleLineRasterizer (void); void init (const tcu::Vec4& v0, const tcu::Vec4& v1, float lineWidth); // only available after init() void rasterize (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized); private: SingleSampleLineRasterizer (const SingleSampleLineRasterizer&); // not allowed SingleSampleLineRasterizer& operator= (const SingleSampleLineRasterizer&); // not allowed // Constant rasterization state. const tcu::IVec4 m_viewport; // Per-line rasterization state. tcu::Vec4 m_v0; tcu::Vec4 m_v1; tcu::IVec2 m_bboxMin; //!< Bounding box min (inclusive). tcu::IVec2 m_bboxMax; //!< Bounding box max (inclusive). tcu::IVec2 m_curPos; //!< Current rasterization position. deInt32 m_curRowFragment; //!< Current rasterization position of one fragment in column of lineWidth fragments float m_lineWidth; } DE_WARN_UNUSED_TYPE; /*--------------------------------------------------------------------*//*! * \brief Multisampled line rasterizer * * Line rasterizer implements following features: * - Rasterization using fixed-point coordinates * - Depth interpolation * - Perspective-correct interpolation * * It does not (and will not) implement following: * - Clipping * - Aliased line rasterization *//*--------------------------------------------------------------------*/ class MultiSampleLineRasterizer { public: MultiSampleLineRasterizer (const int numSamples, const tcu::IVec4& viewport); ~MultiSampleLineRasterizer (); void init (const tcu::Vec4& v0, const tcu::Vec4& v1, float lineWidth); // only available after init() void rasterize (FragmentPacket* const fragmentPackets, float* const depthValues, const int maxFragmentPackets, int& numPacketsRasterized); private: MultiSampleLineRasterizer (const MultiSampleLineRasterizer&); // not allowed MultiSampleLineRasterizer& operator= (const MultiSampleLineRasterizer&); // not allowed // Constant rasterization state. const int m_numSamples; // Per-line rasterization state. TriangleRasterizer m_triangleRasterizer0; //!< not in array because we want to initialize these in the initialization list TriangleRasterizer m_triangleRasterizer1; } DE_WARN_UNUSED_TYPE; /*--------------------------------------------------------------------*//*! * \brief Pixel diamond * * Structure representing a diamond a line exits. *//*--------------------------------------------------------------------*/ struct LineExitDiamond { tcu::IVec2 position; }; /*--------------------------------------------------------------------*//*! * \brief Line exit diamond generator * * For a given line, generates list of diamonds the line exits using the * line-exit rules of the line rasterization. Does not do scissoring. * * \note Not used by rr, but provided to prevent test cases requiring * accurate diamonds from abusing SingleSampleLineRasterizer. *//*--------------------------------------------------------------------*/ class LineExitDiamondGenerator { public: LineExitDiamondGenerator (void); ~LineExitDiamondGenerator (void); void init (const tcu::Vec4& v0, const tcu::Vec4& v1); // only available after init() void rasterize (LineExitDiamond* const lineDiamonds, const int maxDiamonds, int& numWritten); private: LineExitDiamondGenerator (const LineExitDiamondGenerator&); // not allowed LineExitDiamondGenerator& operator= (const LineExitDiamondGenerator&); // not allowed // Per-line rasterization state. tcu::Vec4 m_v0; tcu::Vec4 m_v1; tcu::IVec2 m_bboxMin; //!< Bounding box min (inclusive). tcu::IVec2 m_bboxMax; //!< Bounding box max (inclusive). tcu::IVec2 m_curPos; //!< Current rasterization position. }; } // rr #endif // _RRRASTERIZER_HPP