Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/wpf-gpu-raster/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 96 kB image not shown  

SSL hwvertexbuffer.rs   Sprache: unbekannt

 
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


//-----------------------------------------------------------------------------
//

//
//  Description:
//      Contains HW Vertex Buffer and Builder class implementations
//
//
//  Notes:
//        
//        +--------------------------------------+
//        |                                      |
//        |           Start Stratum              |
//     1  |                                      |
//        |                                      |
//        +--------------------------------------+
//     2  |======================================|
//        +--------------------------------------+
//        |          /   \             / \       |
//        |         /     \           /   \      |
//        |   A    /   B   \    C    /  D  \  E  |
//     3  |       /         \       /       \    |
//        |      /           \     /         \   |
//        |     /             \   /           \  |
//        |    /               \ /             \ |
//        +--------------------------------------+
//        |    \               / \             / |
//        |     \             /   \           /  |
//     4  |  F   \     G     /  H  \    I    / J |
//        |       \         /       \       /    |
//        +--------------------------------------+
//     5  |======================================|
//        +--------------------------------------+
//     6  |======================================|
//        +--------------------------------------+
//        |                                      |
//        |                                      |
//     7  |           Stop Stratum               |
//        |                                      |
//        |                                      |
//        +--------------------------------------+
//        
//  
//  Strata & complement mode.
//  
//  The anti-aliased HW rasterizer produces a series of "strata" where
//  each strata can be a complex span rendered using lines (#'s 2,5,6) or
//  a series of trapezoids (#'s 3 & 4.)  In normal mode the trapezoid
//  regions B,D,G,I are filled in.
//  
//  Complement mode complicates things.  Complex spans are relatively easy
//  because we get the whole line's worth of data at once.  Trapezoids are
//  more complex because we get B,D,G and I separately.  We handle this by
//  tracking the current stratum and finishing the last incomplete
//  trapezoid stratum when a new stratum begins.  Regions E & J finish
//  trapezoid strata.  We also need to add rectangles at the beginning and
//  end of the geometry (start and stop) to fill out the complement
//  region.
//  
//  This is implemented like so:
//  
//    1. Strata are generated from top to bottom without gaps.
//    2. Before drawing any lines or trapezoids call
//       PrepareStratum(a, b, fTrapezoid) where a & b are the extent of
//       the current stratum and fTrapezoid is true if you are drawing
//       a trapezoid.  This will take care of creating the start
//       stratum and/or finishing a trapezoid stratum if necessary.
//    3. When completely done call EndBuildingOutside() which will
//       close a pending trapezoid and/or produce the stop stratum.
//  
//-----------------------------------------------------------------------------

const FORCE_TRIANGLES: bool = true;

//+----------------------------------------------------------------------------
//
//  Constants to control when we stop waffling because the tiles are too
//  small to make a difference.
//
//  Future Consideration:  can produce an excessive number of triangles.
//   How we mitigate or handle this could be improved.  Right now we stop
//   waffling if the waffle size is less than a quarter-pixel.
//   Two big improvements that could be made are:
//    - multipacking very small textures (but note that we cannot rely
//      on prefiltering to ensure that small screen space means small texture
//      source)
//    - clipping primitives to approximately the screen size
//
//-----------------------------------------------------------------------------
//const c_rMinWaffleWidthPixels: f32 = 0.25;


const FLOAT_ZERO: f32 = 0.;
const FLOAT_ONE: f32 = 1.;

//+----------------------------------------------------------------------------
//
//  Class:     CHwVertexBuffer and CHwTVertexBuffer<class TVertex>
//
//  Synopsis:  This class accumulates geometry data for a primitive
//
//-----------------------------------------------------------------------------

use crate::{types::*, geometry_sink::IGeometrySink, aacoverage::c_nShiftSizeSquared, OutputVertex, nullable_ref::Ref};


//+----------------------------------------------------------------------------
//
//  Class:     CHwVertexBuffer::Builder
//
//  Synopsis:  Base vertex builder class
//
//  Responsibilities:
//    - Given ordered basic vertex information expand/convert/pass-thru
//      to vertex buffer  (Basic vertex information is minimal vertex
//      information sent from the caller that may or may not have been
//      passed thru a tessellator.)
//    - Choosing vertex format from a minimal required vertex format
//
//  Not responsible for:
//    - Allocating space in vertex buffer
//
//  Inputs required:
//    - Key and data to translate input basic vertex info to full vertex data
//    - Vertex info from tessellation (or other Geometry Generator)
//    - Vertex buffer to send output to
//

/*pub struct CHwVertexBufferBuilder /* : public IGeometrySink */
{
    /* 
public:

    static HRESULT Create(
        MilVertexFormat vfIn,
        MilVertexFormat vfOut,
        MilVertexFormatAttribute vfaAntiAliasScaleLocation,
        __in_ecount_opt(1) CHwPipeline *pPipeline,
        __in_ecount_opt(1) CD3DDeviceLevel1 *pDevice,
        __in_ecount(1) CBufferDispenser *pBufferDispenser,
        __deref_out_ecount(1) CHwVertexBuffer::Builder **ppVertexBufferBuilder
        );

    virtual ~Builder()
    {
#if DBG
        Assert(!m_fDbgDestroyed);
        m_fDbgDestroyed = true;
#endif DBG
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    SetConstantMapping
    //
    //  Synopsis:  Use this method to specify that the given color source for
    //             the given vertex destination is constant (won't differ per
    //             vertex)
    //
    //-------------------------------------------------------------------------

    virtual HRESULT SetConstantMapping(
        MilVertexFormatAttribute mvfaDestination,
        __in_ecount(1) const CHwConstantColorSource *pConstCS
        ) PURE;


    //+------------------------------------------------------------------------
    //
    //  Member:    FinalizeMappings
    //
    //  Synopsis:  Use this method to let builder know that all mappings have
    //             been sent
    //
    //-------------------------------------------------------------------------

    virtual HRESULT FinalizeMappings(
        ) PURE;

    //+------------------------------------------------------------------------
    //
    //  Member:    SetOutsideBounds
    //
    //  Synopsis:  Enables rendering zero-alpha geometry outside of the input
    //             shape but within the given bounding rectangle, if fNeedInside
    //             isn't true then it doesn't render geometry with full alpha.
    //
    //-------------------------------------------------------------------------
    virtual void SetOutsideBounds(
        __in_ecount_opt(1) const CMILSurfaceRect *prcBounds,
        bool fNeedInside
        ) PURE;

    //+------------------------------------------------------------------------
    //
    //  Member:    HasOutsideBounds
    //
    //  Synopsis:  Returns true if outside bounds have been set.
    //
    //-------------------------------------------------------------------------
    virtual bool HasOutsideBounds() const PURE;

    //+------------------------------------------------------------------------
    //
    //  Member:    BeginBuilding
    //
    //  Synopsis:  This method lets the builder know it should start from a
    //             clean slate
    //
    //-------------------------------------------------------------------------

    virtual HRESULT BeginBuilding(
        ) PURE;

    //+------------------------------------------------------------------------
    //
    //  Member:    EndBuilding
    //
    //  Synopsis:  Use this method to let the builder know that all of the
    //             vertex data has been sent
    //
    //-------------------------------------------------------------------------

    virtual HRESULT EndBuilding(
        __deref_opt_out_ecount(1) CHwVertexBuffer **ppVertexBuffer
        ) PURE;

    //+------------------------------------------------------------------------
    //
    //  Member:    FlushReset
    //
    //  Synopsis:  Send pending state and geometry to the device and reset
    //             the vertex buffer.
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE HRESULT FlushReset()
    {
        return FlushInternal(NULL);
    }
        
    //
    // Currently all CHwVertexBuffer::Builder are supposed to be allocated via
    // a CBufferDispenser.
    //

    DECLARE_BUFFERDISPENSER_DELETE

protected:

    Builder()
    {
        m_mvfIn = MILVFAttrNone;

#if DBG
        m_mvfDbgOut = MILVFAttrNone;
#endif

        m_mvfaAntiAliasScaleLocation = MILVFAttrNone;

        m_pPipelineNoRef = NULL;
        m_pDeviceNoRef = NULL;
        
#if DBG
        m_fDbgDestroyed = false;
#endif DBG
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    FlushInternal
    //
    //  Synopsis:  Send any pending state and geometry to the device.
    //             If the optional argument is NULL then reset the
    //             vertex buffer.
    //             If the optional argument is non-NULL AND we have
    //             not yet flushed the vertex buffer return the vertex
    //             buffer.
    //
    //-------------------------------------------------------------------------

    virtual HRESULT FlushInternal(
        __deref_opt_out_ecount_opt(1) CHwVertexBuffer **ppVertexBuffer
        ) PURE;


    CHwPipeline *m_pPipelineNoRef;
    CD3DDeviceLevel1 *m_pDeviceNoRef;

    MilVertexFormat m_mvfIn;         // Vertex fields that are pre-generated

#if DBG
    MilVertexFormat m_mvfDbgOut;     // Output format of the vertex
#endif

    MilVertexFormat m_mvfGenerated;  // Vertex fields that are dynamically
                                     // generated by this builder

    MilVertexFormatAttribute m_mvfaAntiAliasScaleLocation;  // Vertex field that
                                                            // contains PPAA
                                                            // falloff factor

#if DBG
private:

    bool m_fDbgDestroyed;     // Used to check single Release pattern

#endif DBG
*/
}*/
#[derive(Default)]
pub struct CD3DVertexXYZDUV2 {
    x: f32,
    y: f32,
    //Z: f32,
    coverage: f32,
    /*U0: f32, V0: f32,
    U1: f32, V1: f32,*/
}
pub type CHwVertexBuffer<'z> = CHwTVertexBuffer<'z, OutputVertex>;
#[derive(Default)]
pub struct CHwTVertexBuffer<'z, TVertex>
{
    //m_rgIndices: DynArray<WORD>,     // Dynamic array of indices


    //m_pBuilder: Rc<CHwTVertexBufferBuilder<TVertex>>,

    /* 
#if DBG
public:
    
    CHwTVertexBuffer()
    {
        m_fDbgNonLineSegmentTriangleStrip = false;
    }
#endif

protected:

    //+------------------------------------------------------------------------
    //
    //  Member:    Reset
    //
    //  Synopsis:  Mark the beginning of a new list of vertices; the existing
    //             list is discarded
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE void Reset(
        __in_ecount(1) Builder *pVBB
        )
    {
#if DBG
        m_fDbgNonLineSegmentTriangleStrip = false;
#endif
        m_rgIndices.SetCount(0);
        m_rgVerticesTriList.SetCount(0);
        m_rgVerticesTriStrip.SetCount(0);
        m_rgVerticesLineList.SetCount(0);
        m_rgVerticesNonIndexedTriList.SetCount(0);

        m_pBuilder = pVBB;
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    AddNonIndexedTriListVertices
    //
    //  Synopsis:  Reserve space for consecutive vertices and return start
    //             index
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE HRESULT AddNonIndexedTriListVertices(
        UINT uCount,
        __deref_ecount(uCount) TVertex **ppVertices
        );

    //+------------------------------------------------------------------------
    //
    //  Member:    AddTriListVertices
    //
    //  Synopsis:  Reserve space for consecutive vertices and return start
    //             index
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE HRESULT AddTriListVertices(
        UINT uDelta,
        __deref_ecount(uDelta) TVertex **ppVertices,
        __out_ecount(1) WORD *pwIndexStart
        );

    //+------------------------------------------------------------------------
    //
    //  Member:    AddTriStripVertices
    //
    //  Synopsis:  Reserve space for consecutive vertices and return start
    //             index
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE HRESULT AddTriStripVertices(
        UINT uCount,
        __deref_ecount(uCount) TVertex **ppVertices
        );

    //+------------------------------------------------------------------------
    //
    //  Member:    AddLineListVertices
    //
    //  Synopsis:  Reserve space for consecutive vertices and return start
    //             index
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE HRESULT AddLineListVertices(
        UINT uCount,
        __deref_ecount(uCount) TVertex **ppVertices
        );

public:

    //+------------------------------------------------------------------------
    //
    //  Member:    AddLine implements ILineSink<PointXYA>
    //
    //  Synopsis:  Add a line given two points with x, y, & alpha.
    //
    //-------------------------------------------------------------------------
    HRESULT AddLine(
        __in_ecount(1) const PointXYA &v0,
        __in_ecount(1) const PointXYA &v1
        );

    //+------------------------------------------------------------------------
    //
    //  Member:    AddTriangle implements ITriangleSink<PointXYA>
    //
    //  Synopsis:  Add a triangle given three points with x, y, & alpha.
    //
    //-------------------------------------------------------------------------

    HRESULT AddTriangle(
        __in_ecount(1) const PointXYA &v0,
        __in_ecount(1) const PointXYA &v1,
        __in_ecount(1) const PointXYA &v2
        );

    // Re-introduce parent AddTriangle(WORD,WORD,WORD) into this scope.
    using CHwVertexBuffer::AddTriangle;
    
    //+------------------------------------------------------------------------
    //
    //  Member:    AddLineAsTriangleStrip
    //
    //  Synopsis:  Add a horizontal line using a trinagle strip
    //
    //-------------------------------------------------------------------------
    HRESULT AddLineAsTriangleStrip(
        __in_ecount(1) const TVertex *pBegin, // Begin
        __in_ecount(1) const TVertex *pEnd    // End
        );

    //+------------------------------------------------------------------------
    //
    //  Member:    SendVertexFormat
    //
    //  Synopsis:  Send contained vertex format to device
    //
    //-------------------------------------------------------------------------

    HRESULT SendVertexFormat(
        __inout_ecount(1) CD3DDeviceLevel1 *pDevice
        ) const;

    //+------------------------------------------------------------------------
    //
    //  Member:    DrawPrimitive
    //
    //  Synopsis:  Send the geometry data to the device and execute rendering
    //
    //-------------------------------------------------------------------------

    HRESULT DrawPrimitive(
        __inout_ecount(1) CD3DDeviceLevel1 *pDevice
        ) const;

protected:
    //+------------------------------------------------------------------------
    //
    //  Member:    GetNumTriListVertices
    //
    //  Synopsis:  Return current number of vertices
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE DWORD GetNumTriListVertices() const
    {
        return m_rgVerticesTriList.GetCount();
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    GetTriListVertices
    //
    //  Synopsis:  Return pointer to beginning of vertex list and their count
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE void GetTriListVertices(
        __deref_out_ecount_full(*puNumVertices) TVertex **ppVertices,
        __out_ecount(1) UINT * puNumVertices
        )
    {
        *ppVertices = m_rgVerticesTriList.GetDataBuffer();
        *puNumVertices = m_rgVerticesTriList.GetCount();
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    GetNumNonIndexedTriListVertices
    //
    //  Synopsis:  Return current number of vertices
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE DWORD GetNumNonIndexedTriListVertices() const
    {
        return m_rgVerticesNonIndexedTriList.GetCount();
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    GetNonIndexedTriListVertices
    //
    //  Synopsis:  Return pointer to beginning of vertex list and their count
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE void GetNonIndexedTriListVertices(
        __deref_out_ecount_full(*puNumVertices) TVertex **ppVertices,
        __out_ecount(1) UINT * puNumVertices
        )
    {
        *ppVertices = m_rgVerticesNonIndexedTriList.GetDataBuffer();
        *puNumVertices = m_rgVerticesNonIndexedTriList.GetCount();
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    GetNumTriStripVertices
    //
    //  Synopsis:  Return current number of vertices
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE DWORD GetNumTriStripVertices() const
    {
        return m_rgVerticesTriStrip.GetCount();
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    GetTriStripVertices
    //
    //  Synopsis:  Return pointer to beginning of vertex list and their count
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE void GetTriStripVertices(
        __deref_out_ecount_full(*puNumVertices) TVertex **ppVertices,
        __out_ecount(1) UINT *puNumVertices
        )
    {
        *ppVertices = m_rgVerticesTriStrip.GetDataBuffer();
        *puNumVertices = m_rgVerticesTriStrip.GetCount();
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    GetNumLineListVertices
    //
    //  Synopsis:  Return current number of vertices
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE DWORD GetNumLineListVertices() const
    {
        return m_rgVerticesLineList.GetCount();
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    GetLineListVertices
    //
    //  Synopsis:  Return pointer to beginning of vertex list and their count
    //
    //-------------------------------------------------------------------------

    MIL_FORCEINLINE void GetLineListVertices(
        __deref_out_ecount_full(*puNumVertices) TVertex **ppVertices,
        __out_ecount(1) UINT * puNumVertices
        )
    {
        *ppVertices = m_rgVerticesLineList.GetDataBuffer();
        *puNumVertices = m_rgVerticesLineList.GetCount();
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    GetLineListVertices
    //
    //  Synopsis:  Return pointer to beginning of vertex list
    //
    //-------------------------------------------------------------------------



*/

    // Dynamic array of vertices for which all allocations are zeroed.
    // XXX: the zero has been removed
    //m_rgVerticesTriList: DynArray<TVertex>,             // Indexed triangle list vertices
    //m_rgVerticesNonIndexedTriList: DynArray<TVertex>,   // Non-indexed triangle list vertices
    m_rgVerticesTriList: DynArray<TVertex>,            // Triangle strip vertices
    //m_rgVerticesLineList: DynArray<TVertex>,            // Linelist vertices

    m_rgVerticesBuffer: Option<&'z mut [TVertex]>,
    m_rgVerticesBufferOffset: usize,

    #[cfg(debug_assertions)]
    // In debug make a note if we add a triangle strip that doesn't have 6 vertices
    // so that we can ensure that we only waffle 6-vertex tri strips.
    m_fDbgNonLineSegmentTriangleStrip: bool,
    subpixel_bias: f32,
}

impl<'z, TVertex: Default> CHwTVertexBuffer<'z, TVertex> {
    pub fn new(rasterization_truncates: bool, output_buffer: Option<&'z mut [TVertex]>) -> Self {
        CHwTVertexBuffer::<TVertex> {
            subpixel_bias: if rasterization_truncates {
                // 1/512 is 0.5 of a subpixel when using 8 bits of subpixel precision.
                1./512.
            } else {
                0.
            },
            m_rgVerticesBuffer: output_buffer,
            m_rgVerticesBufferOffset: 0,
            ..Default::default()
        }
    }

    pub fn flush_output(&mut self) -> Box<[TVertex]> {
        std::mem::take(&mut self.m_rgVerticesTriList).into_boxed_slice()
    }

    pub fn get_output_buffer_size(&self) -> Option<usize> {
        if self.m_rgVerticesBuffer.is_some() {
            Some(self.m_rgVerticesBufferOffset)
        } else {
            None
        }
    }
}

//+----------------------------------------------------------------------------
//
//  Class:     CHwTVertexMappings<class TVertex>
//
//  Synopsis:  Helper class that knows how to populate a vertex from the
//             incoming basic per vertex data, like just X and Y
//
//-----------------------------------------------------------------------------
#[derive(Default)]
struct CHwTVertexMappings<TVertex>
{/* 
public:

    CHwTVertexMappings();

    void SetPositionTransform(
        __in_ecount(1) const MILMatrix3x2 &matPositionTransform
        );

    HRESULT SetConstantMapping(
        MilVertexFormatAttribute mvfaDestination,
        __in_ecount(1) const CHwConstantColorSource *pConstCS
        );

    void PointToUV(
        __in_ecount(1) const MilPoint2F &ptIn,
        __bound UINT uIndex,
        __out_ecount(1) TVertex *pvOut
        );
    
    MIL_FORCEINLINE bool AreWaffling() const
    {
        return false;
    }

private:
    static const size_t s_numOfVertexTextureCoords
        = NUM_OF_VERTEX_TEXTURE_COORDS(TVertex);
public:

    MilVertexFormat m_mvfMapped;

    MilColorF m_colorStatic;

    MILMatrix3x2 m_matPos2DTransform;

    MILMatrix3x2 m_rgmatPointToUV[s_numOfVertexTextureCoords];
    CMilPointAndSizeF m_rgSubrect[s_numOfVertexTextureCoords];
    WaffleModeFlags m_rgWaffleMode[s_numOfVertexTextureCoords];

*/
    m_vStatic: TVertex,
    subpixel_bias: f32,
}

impl<TVertex> CHwTVertexBuffer<'_, TVertex> {
    pub fn Reset(&mut self,
        /*pVBB: &mut CHwTVertexBufferBuilder<TVertex>*/
        )
    {
        #[cfg(debug_assertions)]
        {
            self.m_fDbgNonLineSegmentTriangleStrip = false;
        }

        //self.m_rgIndices.SetCount(0);
        //self.m_rgVerticesTriList.SetCount(0);
        self.m_rgVerticesTriList.SetCount(0);
        self.m_rgVerticesBufferOffset = 0;
        //self.m_rgVerticesLineList.SetCount(0);
        //self.m_rgVerticesNonIndexedTriList.SetCount(0);

        //self.m_pBuilder = pVBB;
    }

    fn IsEmpty(&self) -> bool
    {
        return true
             //  && (self.m_rgIndices.GetCount() == 0)
            //&& (self.m_rgVerticesLineList.GetCount() == 0)
            && (self.m_rgVerticesTriList.GetCount() == 0)
            && self.m_rgVerticesBufferOffset == 0
            //&& (self.m_rgVerticesNonIndexedTriList.GetCount() == 0);
    }

}

//+----------------------------------------------------------------------------
//
//  Class:     CHwTVertexBuffer<class TVertex>::Builder
//
//  Synopsis:  Implements CHwVertexBuffer::Builder for a particular vertex
//             format
//
//-----------------------------------------------------------------------------

pub struct CHwTVertexBufferBuilder<'y, 'z, TVertex>
{
    m_mvfIn: MilVertexFormat,         // Vertex fields that are pre-generated

    #[cfg(debug_assertions)]
    m_mvfDbgOut: MilVertexFormat,     // Output format of the vertex
    
    m_mvfGenerated: MilVertexFormat,  // Vertex fields that are dyn

    m_mvfaAntiAliasScaleLocation: MilVertexFormatAttribute,  // Vertex field that
                                                             // contains PPAA
                                                             // falloff factor

    /*
public:

    static MilVertexFormat GetOutVertexFormat();

    static HRESULT Create(
        __in_ecount(1) CHwTVertexBuffer<TVertex> *pVertexBuffer,
        MilVertexFormat mvfIn,
        MilVertexFormat mvfOut,
        MilVertexFormatAttribute mvfaAntiAliasScaleLocation,
        __inout_ecount(1) CBufferDispenser *pBufferDispenser,
        __deref_out_ecount(1) typename CHwTVertexBuffer<TVertex>::Builder **ppVertexBufferBuilder
        );

    HRESULT SetConstantMapping(
        MilVertexFormatAttribute mvfaDestination,
        __in_ecount(1) const CHwConstantColorSource *pConstCS
        );

    void SetTransformMapping(
        __in_ecount(1) const MILMatrix3x2 &mat2DTransform
        );

    HRESULT FinalizeMappings(
        );

    void SetOutsideBounds(
        __in_ecount_opt(1) const CMILSurfaceRect *prcBounds,
        bool fNeedInside
        );

    bool HasOutsideBounds() const
    {
        return NeedOutsideGeometry();
    }

    HRESULT BeginBuilding(
        );

    HRESULT AddVertex(
        __in_ecount(1) const MilPoint2F &ptPosition,
            // In: Vertex coordinates
        __out_ecount(1) WORD *pIndex
            // Out: The index of the new vertex
        );

    HRESULT AddIndexedVertices(
        UINT cVertices,                                                  // In: number of vertices                                                                                            
        __in_bcount(cVertices*uVertexStride) const void *pVertexBuffer,  // In: vertex buffer containing the vertices                                                                         
        UINT uVertexStride,                                              // In: size of each vertex                                                                                           
        MilVertexFormat mvfFormat,                                       // In: format of each vertex                                                                                         
        UINT cIndices,                                                   // In: Number of indices                                                                                             
        __in_ecount(cIndices) const UINT *puIndexBuffer                  // In: index buffer                                                             
        );

    HRESULT AddTriangle(
        DWORD i1,                    // In: Index of triangle's first vertex
        DWORD i2,                    // In: Index of triangle's second vertex
        DWORD i3                     // In: Index of triangle's third vertex
        );

    HRESULT AddComplexScan(
        INT nPixelY,
            // In: y coordinate in pixel space
        __in_ecount(1) const CCoverageInterval *pIntervalSpanStart
            // In: coverage segments
        );

   HRESULT AddParallelogram(
        __in_ecount(4)  const MilPoint2F *rgPosition
        );
   
    HRESULT AddTrapezoid(
        float rPixelYTop,               // In: y coordinate of top of trapezoid
        float rPixelXTopLeft,           // In: x coordinate for top left
        float rPixelXTopRight,          // In: x coordinate for top right
        float rPixelYBottom,            // In: y coordinate of bottom of trapezoid
        float rPixelXBottomLeft,        // In: x coordinate for bottom left
        float rPixelXBottomRight,       // In: x coordinate for bottom right
        float rPixelXLeftDelta,         // In: trapezoid expand radius for left edge
        float rPixelXRightDelta         // In: trapezoid expand radius for right edge
        );

    BOOL IsEmpty();

    HRESULT EndBuilding(
        __deref_opt_out_ecount(1) CHwVertexBuffer **ppVertexBuffer
        );

    HRESULT FlushInternal(
        __deref_opt_out_ecount_opt(1) CHwVertexBuffer **ppVertexBuffer
        );
            
private:

    // Helpers that do AddTrapezoid.  Same parameters
    HRESULT AddTrapezoidStandard( float, float, float, float, float, float, float, float );
    HRESULT AddTrapezoidWaffle( float, float, float, float, float, float, float, float );


    
    HRESULT PrepareStratumSlow(
        float rStratumTop,
        float rStratumBottom,
        bool fTrapezoid,
        float rTrapezoidLeft,
        float rTrapezoidRight
        );
    
    // Wrap up building of outside geometry.
    HRESULT EndBuildingOutside();

    DECLARE_BUFFERDISPENSER_NEW(CHwTVertexBuffer<TVertex>::Builder,
                                Mt(CHwTVertexBuffer_Builder));

    Builder(
        __in_ecount(1) CHwTVertexBuffer<TVertex> *pVertexBuffer
    );

    HRESULT SetupConverter(
        MilVertexFormat mvfIn,
        MilVertexFormat mvfOut,
        MilVertexFormatAttribute mvfaAntiAliasScaleLocation
        );

    HRESULT RenderPrecomputedIndexedTriangles(
        __range(1, SHORT_MAX) UINT cVertices,
        __in_ecount(cVertices) const TVertex *rgoVertices,
        __range(1, UINT_MAX) UINT cIndices,
        __in_ecount(cIndices) const UINT *rguIndices
        );


    // Expands all vertices in the buffer.
    void ExpandVertices();
    
    // Has never been successfully used to declare a method or derived type...
/*    typedef void (CHwTVertexBuffer<TVertex>::Builder::FN_ExpandVertices)(
        UINT uCount,
        TVertex *pVertex
        );*/

    // error C2143: syntax error : missing ';' before '*'
//    typedef FN_ExpandVertices *PFN_ExpandVertices;

    typedef void (CHwTVertexBuffer<TVertex>::Builder::* PFN_ExpandVertices)(
        __range(1,UINT_MAX) UINT uCount,
        __inout_ecount_full(uCount) TVertex *rgVertices
        );

    //
    // Table of vertex expansion routines for common expansion cases:
    //  - There are entries for Z, Diffuse, and one set texture coordinates for
    //    a total of eight combinations.
    //  - Additionally there is a second set of entries for anti-aliasing
    //    falloff applied thru diffuse.
    //

    static const PFN_ExpandVertices sc_pfnExpandVerticesTable[8*2];

    MIL_FORCEINLINE
    void TransferAndOrExpandVerticesInline(
        __range(1,UINT_MAX) UINT uCount,
        __in_ecount(uCount) TVertex const * rgInputVertices,
        __out_ecount(uCount) TVertex *rgOutputVertices,
        MilVertexFormat mvfOut,
        MilVertexFormatAttribute mvfaScaleByFalloff,
        bool fInputOutputAreSameBuffer,
        bool fTransformPosition
        );

    // FN_ExpandVertices ExpandVerticesFast
    template <MilVertexFormat mvfOut, MilVertexFormatAttribute mvfaScaleByFalloff>
    void ExpandVerticesFast(
        __range(1,UINT_MAX) UINT uCount,
        __inout_ecount_full(uCount) TVertex *rgVertices
        )
    {
        TransferAndOrExpandVerticesInline(
            uCount, 
            rgVertices, 
            rgVertices, 
            mvfOut, 
            mvfaScaleByFalloff,
            true, // => fInputOutputAreSameBuffer
            false // => fTransformPosition
            );
    }

    // error C2146: syntax error : missing ';' before identifier 'ExpandVerticesGeneral'
    // error C2501: 'CHwTVertexBufferBuilder<TVertex>::FN_ExpandVertices' : missing storage-class or type specifiers
//    FN_ExpandVertices ExpandVerticesGeneral
//    typename FN_ExpandVertices ExpandVerticesGeneral
    // error C4346: 'CHwTVertexBufferBuilder<TVertex>::FN_ExpandVertices' : dependent name is not a type
//    CHwTVertexBufferBuilder<TVertex>::FN_ExpandVertices ExpandVerticesGeneral
    // Can't define methos here (unless not parameters are used).
//    typename CHwTVertexBufferBuilder<TVertex>::FN_ExpandVertices ExpandVerticesGeneral
    // FN_ExpandVertices ExpandVerticesGeneral
    void ExpandVerticesGeneral(
        __range(1,UINT_MAX) UINT uCount,
        __inout_ecount_full(uCount) TVertex *rgVertices
        )
    {
        TransferAndOrExpandVerticesInline(
            uCount, 
            rgVertices,
            rgVertices,
            m_mvfGenerated, 
            m_mvfaAntiAliasScaleLocation,
            true, // => fInputOutputAreSameBuffer
            false // => fTransformPosition
            );
    }

    void TransferAndExpandVerticesGeneral(
        __range(1,UINT_MAX) UINT uCount,
        __in_ecount(uCount) TVertex const *rgInputVertices,
        __out_ecount_full(uCount) TVertex *rgOutputVertices,
        bool fTransformPosition
        )
    {
        TransferAndOrExpandVerticesInline(
            uCount, 
            rgInputVertices,
            rgOutputVertices,
            m_mvfGenerated, 
            m_mvfaAntiAliasScaleLocation,
            false,              // => fInputOutputAreSameBuffer
            fTransformPosition  // => fTransformPosition
            );
    }

    // FN_ExpandVertices ExpandVerticesInvalid
    void ExpandVerticesInvalid(
        __range(1,UINT_MAX) UINT uCount,
        __inout_ecount_full(uCount) TVertex *rgVertices
        )
    {
        RIP("Invalid ExpandVertices routine.");
    }

    //+------------------------------------------------------------------------
    //
    //  Member:    NeedCoverageGeometry
    //
    //  Synopsis:  True if we should create geometry for a particular
    //             coverage value.
    //
    //-------------------------------------------------------------------------
    bool NeedCoverageGeometry(INT nCoverage) const;





    //+------------------------------------------------------------------------
    //
    //  Member:    ReinterpretFloatAsDWORD
    //
    //  Synopsis:  Quicky helper to convert a float to a DWORD bitwise.
    //
    //-------------------------------------------------------------------------
    static MIL_FORCEINLINE DWORD ReinterpretFloatAsDWORD(float c)
    {
        return reinterpret_cast<DWORD &>(c);
    }

private:
    MIL_FORCEINLINE bool AreWaffling() const
    {
        return m_map.AreWaffling();
    }
   
    void ViewportToPackedCoordinates(
        __range(1,UINT_MAX / uGroupSize) UINT uGroupCount,        
        __inout_ecount(uGroupCount * uGroupSize) TVertex *pVertex,
        __range(2,6) UINT uGroupSize,
        /*__range(0,NUM_OF_VERTEX_TEXTURE_COORDS(TVertex)-1)*/ __bound UINT uIndex
        );
    
    void ViewportToPackedCoordinates(
        __range(1,UINT_MAX / uGroupSize) UINT uGroupCount,
        __inout_ecount(uGroupCount * uGroupSize) TVertex *pVertex,
        __range(2,6) UINT uGroupSize
        );

    template<class TWaffler>
    __out_ecount(1) typename TWaffler::ISink *
    BuildWafflePipeline(
        __out_xcount(NUM_OF_VERTEX_TEXTURE_COORDS(TVertex) * 2) TWaffler *wafflers,
        __out_ecount(1) bool &fWafflersUsed
        ) const;

    
    template<class TWaffler>
    typename TWaffler::ISink *
    BuildWafflePipeline(
        __out_xcount(NUM_OF_VERTEX_TEXTURE_COORDS(TVertex) * 2) TWaffler *wafflers
        ) const
    {
        bool fNotUsed;
        return BuildWafflePipeline(wafflers, fNotUsed);
    }*/

    m_pVB: &'y mut CHwTVertexBuffer<'z, TVertex>,

    //m_pfnExpandVertices: PFN_ExpandVertices,  // Method for expanding vertices

    //m_rgoPrecomputedTriListVertices: *const TVertex,
    //m_cPrecomputedTriListVertices: UINT,

    //m_rguPrecomputedTriListIndices: *const UINT,
    //m_cPrecomputedTriListIndices: UINT,

    //m_map: CHwTVertexMappings<TVertex>,

    // This is true if we had to flush the pipeline as we were getting
    // geometry rather than just filling up a single vertex buffer.
    m_fHasFlushed: bool,

    // The next two members control the generation of the zero-alpha geometry
    // outside the input geometry.
    m_fNeedOutsideGeometry: bool,
    m_fNeedInsideGeometry: bool,
    m_rcOutsideBounds: CMILSurfaceRect, // Bounds for creation of outside geometry

    /* 
    // Helpful m_rcOutsideBounds casts.
    float OutsideLeft() const { return static_cast<float>(m_rcOutsideBounds.left); }
    float OutsideRight() const { return static_cast<float>(m_rcOutsideBounds.right); }
    float OutsideTop() const { return static_cast<float>(m_rcOutsideBounds.top); }
    float OutsideBottom() const { return static_cast<float>(m_rcOutsideBounds.bottom); }
    */
    // This interval (if we are doing outside) shows the location
    // of the current stratum.  It is initialized to [FLT_MAX, -FLT_MAX].
    //
    // If the current stratum is a complex span then
    // m_rCurStratumBottom is set to the bottom of the stratum and
    // m_rCurStratumTop is set to FLT_MAX.
    //
    // If the current stratum is a trapezoidal one, then
    // m_rCurStratumBottom is its bottom and m_rCurStratumTop is its
    // top.
    m_rCurStratumTop: f32,
    m_rCurStratumBottom: f32,

    // If the current stratum is a trapezoidal one, following var stores
    // right boundary of the last trapezoid handled by PrepareStratum.
    // We need it to cloze the stratus properly.
    m_rLastTrapezoidRight: f32,

    // These are needed to implement outside geometry using triangle lists
    m_rLastTrapezoidTopRight: f32,
    m_rLastTrapezoidBottomRight: f32,
}

/*
//+----------------------------------------------------------------------------
//
//  Member:    CHwVertexBuffer::AddTriangle
//
//  Synopsis:  Add a triangle using the three indices given to the list
//
impl CHwVertexBuffer {

fn AddTriangle(
    i1: WORD,         // In: Index of triangle's first vertex
    i2: WORD,         // In: Index of triangle's second vertex
    i3: WORD          // In: Index of triangle's third vertex
    ) -> HRESULT
{
    let hr: HRESULT = S_OK;

    // Asserting indices < max vertex requires a debug only pure virtual method
    // which is too much of a functionality change between retail and debug.
    //
    //
    // Assert(i1 < GetNumTriListVertices());
    // Assert(i2 < GetNumTriListVertices());
    // Assert(i3 < GetNumTriListVertices());

    WORD *pIndices;

    IFC(m_rgIndices.AddMultiple(3, &pIndices));

    pIndices[0] = i1;
    pIndices[1] = i2;
    pIndices[2] = i3;

Cleanup:
    RRETURN(hr);
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::AddTriangle
//
//  Synopsis:  Add a triangle using given three points to the list
//
//-----------------------------------------------------------------------------
template <class TVertex>
HRESULT
CHwTVertexBuffer<TVertex>::AddTriangle(
    __in_ecount(1) const PointXYA &v0,
    __in_ecount(1) const PointXYA &v1,
    __in_ecount(1) const PointXYA &v2)
{
    let hr: HRESULT = S_OK;
    
    TVertex *pVertices;
    hr = AddNonIndexedTriListVertices(3,&pVertices);

    if (hr == E_OUTOFMEMORY)
    {
        DebugBreak ();
    }
    IFC(hr);
    
    pVertices[0].ptPt.X = v0.x;
    pVertices[0].ptPt.Y = v0.y;
    pVertices[0].Diffuse = reinterpret_cast<const DWORD &>(v0.a);
    pVertices[1].ptPt.X = v1.x;
    pVertices[1].ptPt.Y = v1.y;
    pVertices[1].Diffuse = reinterpret_cast<const DWORD &>(v1.a);
    pVertices[2].ptPt.X = v2.x;
    pVertices[2].ptPt.Y = v2.y;
    pVertices[2].Diffuse = reinterpret_cast<const DWORD &>(v2.a);

Cleanup:
    RRETURN(hr);
}
*/

impl CHwVertexBuffer<'_> {
//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::AddLine
//
//  Synopsis:  Add a nominal width line using given two points to the list
//
//-----------------------------------------------------------------------------
fn AddLine(&mut self,
    v0: &PointXYA,
    v1: &PointXYA
    ) -> HRESULT
{
    type TVertex = CD3DVertexXYZDUV2;
    let hr = S_OK;

    let pVertices: &mut [TVertex];
    let mut rgScratchVertices: [TVertex; 2] = Default::default();

    assert!(!(v0.y != v1.y));
    
    let fUseTriangles = /*(v0.y < m_pBuilder->GetViewportTop() + 1) ||*/ FORCE_TRIANGLES;

    //if (fUseTriangles)
    //{
        pVertices = &mut rgScratchVertices;
    //}
    //else
    //{
        //IFC!(AddLineListVertices(2, &pVertices));
    //}
    
    pVertices[0].x = v0.x;
    pVertices[0].y = v0.y;
    pVertices[0].coverage = v0.a;
    pVertices[1].x = v1.x;
    pVertices[1].y = v1.y;
    pVertices[1].coverage = v1.a;

    if (fUseTriangles)
    {
        IFC!(self.AddLineAsTriangleList(&pVertices[0],&pVertices[1]));
    }
    
    RRETURN!(hr);
}
}
/* 
//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::AddTriListVertices
//
//  Synopsis:  Reserve space for consecutive vertices and return start index
//

template <class TVertex>
MIL_FORCEINLINE
HRESULT
CHwTVertexBuffer<TVertex>::AddTriListVertices(
    UINT uDelta,
    __deref_ecount(uDelta) TVertex **ppVertices,
    __out_ecount(1) WORD *pwIndexStart
    )
{
    HRESULT hr = S_OK;

    Assert(ppVertices);

    UINT uCount = static_cast<UINT>(m_rgVerticesTriList.GetCount());
    if (uCount > SHRT_MAX)
    {
        IFC(WGXERR_INVALIDPARAMETER);
    }
    UINT newCount;
    newCount = uDelta + uCount;

    if (newCount > SHRT_MAX)
    {
        IFC(m_pBuilder->FlushReset());
        uCount = 0;
        newCount = uDelta;
    }

    if (newCount > m_rgVerticesTriList.GetCapacity())
    {
        IFC(m_rgVerticesTriList.ReserveSpace(uDelta));
    }

    m_rgVerticesTriList.SetCount(newCount);
    *pwIndexStart = static_cast<WORD>(uCount);
    *ppVertices = &m_rgVerticesTriList[uCount];

  Cleanup:
    RRETURN(hr);
}
*/

impl<TVertex: Clone + Default> CHwTVertexBuffer<'_, TVertex> {

fn AddTriVertices(&mut self, v0: TVertex, v1: TVertex, v2: TVertex) {
    if let Some(output_buffer) = &mut self.m_rgVerticesBuffer {
        let offset = self.m_rgVerticesBufferOffset;
        if offset + 3 <= output_buffer.len() {
            output_buffer[offset] = v0;
            output_buffer[offset + 1] = v1;
            output_buffer[offset + 2] = v2;
        }
        self.m_rgVerticesBufferOffset = offset + 3;
    } else {
        self.m_rgVerticesTriList.reserve(3);
        self.m_rgVerticesTriList.push(v0);
        self.m_rgVerticesTriList.push(v1);
        self.m_rgVerticesTriList.push(v2);
    }
}

fn AddTrapezoidVertices(&mut self, v0: TVertex, v1: TVertex, v2: TVertex, v3: TVertex) {
    if let Some(output_buffer) = &mut self.m_rgVerticesBuffer {
        let offset = self.m_rgVerticesBufferOffset;
        if offset + 6 <= output_buffer.len() {
            output_buffer[offset] = v0;
            output_buffer[offset + 1] = v1.clone();
            output_buffer[offset + 2] = v2.clone();

            output_buffer[offset + 3] = v1;
            output_buffer[offset + 4] = v2;
            output_buffer[offset + 5] = v3;
        }
        self.m_rgVerticesBufferOffset = offset + 6;
    } else {
        self.m_rgVerticesTriList.reserve(6);

        self.m_rgVerticesTriList.push(v0);
        self.m_rgVerticesTriList.push(v1.clone());
        self.m_rgVerticesTriList.push(v2.clone());

        self.m_rgVerticesTriList.push(v1);
        self.m_rgVerticesTriList.push(v2);
        self.m_rgVerticesTriList.push(v3);
    }
}

fn AddedNonLineSegment(&mut self) {
    #[cfg(debug_assertions)]
    {
        self.m_fDbgNonLineSegmentTriangleStrip = true;
    }
}

}

/* 
//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::AddNonIndexedTriListVertices
//
//  Synopsis:  Reserve space for triangle list vertices.
//

template <class TVertex>
MIL_FORCEINLINE
HRESULT
CHwTVertexBuffer<TVertex>::AddNonIndexedTriListVertices(
    UINT uCount,
    __deref_ecount(uCount) TVertex **ppVertices
    )
{
    HRESULT hr = S_OK;

    UINT Count = static_cast<UINT>(m_rgVerticesNonIndexedTriList.GetCount());
    UINT newCount = Count + uCount;

    if (newCount > m_rgVerticesNonIndexedTriList.GetCapacity())
    {
        IFC(m_rgVerticesNonIndexedTriList.ReserveSpace(uCount));
    }

    m_rgVerticesNonIndexedTriList.SetCount(newCount);
    *ppVertices = &m_rgVerticesNonIndexedTriList[Count];

Cleanup:
    RRETURN(hr);
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::AddLineListVertices
//
//  Synopsis:  Reserve space for consecutive vertices
//

template <class TVertex>
MIL_FORCEINLINE
HRESULT
CHwTVertexBuffer<TVertex>::AddLineListVertices(
    UINT uCount,
    __deref_ecount(uCount) TVertex **ppVertices
    )
{
    HRESULT hr = S_OK;

    Assert(ppVertices);

    UINT Count = static_cast<UINT>(m_rgVerticesLineList.GetCount());
    UINT newCount = Count + uCount;

    if (newCount > m_rgVerticesLineList.GetCapacity())
    {
        IFC(m_rgVerticesLineList.ReserveSpace(uCount));
    }

    m_rgVerticesLineList.SetCount(newCount);
    *ppVertices = &m_rgVerticesLineList[Count];

Cleanup:
    RRETURN(hr);
}

//+----------------------------------------------------------------------------
//
//  Class:     CHwVertexBuffer::Builder
//
//-----------------------------------------------------------------------------

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::GetOutVertexFormat
//
//  Synopsis:  Return MIL vertex format covered by specific builders
//
//-----------------------------------------------------------------------------

template <>
MilVertexFormat
CHwTVertexBuffer<CD3DVertexXYZDUV2>::Builder::GetOutVertexFormat()
{
    return (MILVFAttrXYZ | MILVFAttrDiffuse | MILVFAttrUV2);
}

template <>
MilVertexFormat
CHwTVertexBuffer<CD3DVertexXYZDUV8>::Builder::GetOutVertexFormat()
{
    return (MILVFAttrXYZ | MILVFAttrDiffuse | MILVFAttrUV8);
}

template <>
MilVertexFormat
CHwTVertexBuffer<CD3DVertexXYZDUV6>::Builder::GetOutVertexFormat()
{
    return (MILVFAttrXYZ | MILVFAttrDiffuse | MILVFAttrUV6);
}

template <>
MilVertexFormat
CHwTVertexBuffer<CD3DVertexXYZNDSUV4>::Builder::GetOutVertexFormat()
{
    return (MILVFAttrXYZ |
            MILVFAttrNormal |
            MILVFAttrDiffuse |
            MILVFAttrSpecular |
            MILVFAttrUV4);
}


//+----------------------------------------------------------------------------
//
//  Member:    CHwVertexBuffer::Builder::Create
//
//  Synopsis:  Choose the appropriate final vertex format and instantiate the
//             matching vertex builder
//
*/
pub type CHwVertexBufferBuilder<'y, 'z> = CHwTVertexBufferBuilder<'y, 'z, OutputVertex>;
impl<'y, 'z> CHwVertexBufferBuilder<'y, 'z> {
pub fn Create(
     vfIn: MilVertexFormat,
     vfOut: MilVertexFormat,
     mvfaAntiAliasScaleLocation: MilVertexFormatAttribute,
    pVertexBuffer: &'y mut CHwVertexBuffer<'z>,
    /*pBufferDispenser: &CBufferDispenser*/
    ) -> CHwVertexBufferBuilder<'y, 'z>
{
    CHwVertexBufferBuilder::CreateTemplate(pVertexBuffer, vfIn, vfOut, mvfaAntiAliasScaleLocation)
    //let hr: HRESULT = S_OK;

    //assert!(ppVertexBufferBuilder);

    //*ppVertexBufferBuilder = None;
/* 
    if (!(vfOut & ~CHwTVertexBuffer<CD3DVertexXYZDUV2>::Builder::GetOutVertexFormat()))
    {
        CHwTVertexBuffer<CD3DVertexXYZDUV2> *pVB = pDevice->GetVB_XYZDUV2();
        CHwTVertexBuffer<CD3DVertexXYZDUV2>::Builder *pVBB = NULL;

        IFC(CHwTVertexBuffer<CD3DVertexXYZDUV2>::Builder::Create(
            pVB,
            vfIn,
            vfOut,
            mvfaAntiAliasScaleLocation,
            pBufferDispenser,
            &pVBB
            ));
        
        *ppVertexBufferBuilder = pVBB;
    }
    else if (!(vfOut & ~CHwTVertexBuffer<CD3DVertexXYZDUV8>::Builder::GetOutVertexFormat()))
    {
        CHwTVertexBuffer<CD3DVertexXYZDUV8> *pVB = pDevice->GetVB_XYZRHWDUV8();
        CHwTVertexBuffer<CD3DVertexXYZDUV8>::Builder *pVBB = NULL;

        IFC(CHwTVertexBuffer<CD3DVertexXYZDUV8>::Builder::Create(
            pVB,
            vfIn,
            vfOut,
            mvfaAntiAliasScaleLocation,
            pBufferDispenser,
            &pVBB
            ));

        *ppVertexBufferBuilder = pVBB;
    }
    else
    {
        // NOTE-2004/03/22-chrisra Adding another vertexbuffer type requires updating enum
        //
        // If we add another buffer builder type kMaxVertexBuilderSize enum in hwvertexbuffer.h file
        // needs to be updated to reflect possible changes to the maximum size of buffer builders.
        //
        IFC(E_NOTIMPL);
    }

    // Store the pipeline, if any, which this VBB can use to spill the vertex buffer to if it
    // overflows.
    (**ppVertexBufferBuilder).m_pPipelineNoRef = pPipeline;
    (**ppVertexBufferBuilder).m_pDeviceNoRef = pDevice;


Cleanup:
    RRETURN(hr);*/
    //hr
}
    /*fn AreWafffling(&self) -> bool {
        false
    }*/

        // Helpful m_rcOutsideBounds casts.
        fn OutsideLeft(&self) -> f32  { return self.m_rcOutsideBounds.left as f32; }
        fn OutsideRight(&self) -> f32 { return self.m_rcOutsideBounds.right as f32; }
        fn OutsideTop(&self) -> f32 { return self.m_rcOutsideBounds.top as f32; }
        fn OutsideBottom(&self) -> f32 { return self.m_rcOutsideBounds.bottom as f32; }
}

//+----------------------------------------------------------------------------
//
//  Class:     THwTVertexMappings<class TVertex>
//
//-----------------------------------------------------------------------------

//+----------------------------------------------------------------------------
//
//  Member:    THwTVertexMappings<TVertex>::THwTVertexMappings
//
//  Synopsis:  ctor
//
//-----------------------------------------------------------------------------
/* 
template <class TVertex>
CHwTVertexMappings<TVertex>::CHwTVertexMappings()
 :
    m_mvfMapped(MILVFAttrNone)
{
    for (int i = 0; i < ARRAY_SIZE(m_rgWaffleMode); ++i)
    {
        m_rgWaffleMode[i] = WaffleModeNone;
    }

    m_matPos2DTransform.SetIdentity();
}


//+----------------------------------------------------------------------------
//
//  Member:    THwTVertexMappings<TVertex>::SetPositionTransform
//
//  Synopsis:  Sets the position transform that needs to be applied.
//
//-----------------------------------------------------------------------------
template <class TVertex>
void 
CHwTVertexMappings<TVertex>::SetPositionTransform(
    __in_ecount(1) const MILMatrix3x2 &matPositionTransform
    )
{
    m_matPos2DTransform = matPositionTransform;
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexMappings<TVertex>::SetConstantMapping
//
//  Synopsis:  Remember the static color for the given vertex field
//

template <class TVertex>
HRESULT
CHwTVertexMappings<TVertex>::SetConstantMapping(
    MilVertexFormatAttribute mvfaLocation,
    __in_ecount(1) const CHwConstantColorSource *pConstCS
    )
{
    HRESULT hr = S_OK;

    Assert(!(m_mvfMapped & mvfaLocation));
    pConstCS->GetColor(m_colorStatic);
    m_mvfMapped |= mvfaLocation;    // Remember this field has been mapped

    RRETURN(hr);
}

//+----------------------------------------------------------------------------
//
//  Function:  GetMILVFAttributeOfTextureCoord
//
//  Synopsis:  Compute MilVertexFormatAttribute for a texture coordinate index
//

MIL_FORCEINLINE
MilVertexFormat
GetMILVFAttributeOfTextureCoord(
    DWORD dwCoordIndex
    )
{
    return MILVFAttrUV1 << dwCoordIndex;
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexMappings<TVertex>::PointToUV
//
//  Synopsis:  Helper function to populate the texture coordinates at the given
//             index using the given point
//

template <class TVertex>
MIL_FORCEINLINE void
CHwTVertexMappings<TVertex>::PointToUV(
    __in_ecount(1) const MilPoint2F &ptIn,
    __bound UINT uIndex,
    __out_ecount(1) TVertex *pvOut
    )
{
    m_rgmatPointToUV[uIndex].TransformPoint(
        &pvOut->ptTx[uIndex],
        ptIn.X,
        ptIn.Y
        );
}





//+----------------------------------------------------------------------------
//
//  Class:     CHwTVertexBuffer<TVertex>::Builder
//
//-----------------------------------------------------------------------------


*/

impl<'y, 'z, TVertex: Default> CHwTVertexBufferBuilder<'y, 'z, TVertex> {

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::Create
//
//  Synopsis:  Instantiate a specific type of vertex builder
//

fn CreateTemplate(
     pVertexBuffer: &'y mut CHwTVertexBuffer<'z, TVertex>,
     mvfIn: MilVertexFormat,
     mvfOut: MilVertexFormat,
     mvfaAntiAliasScaleLocation: MilVertexFormatAttribute,
     /*pBufferDispenser: __inout_ecount(1) CBufferDispenser *,*/
    ) -> Self
{



    let mut pVertexBufferBuilder = CHwTVertexBufferBuilder::<TVertex>::new(pVertexBuffer);

    IFC!(pVertexBufferBuilder.SetupConverter(
        mvfIn,
        mvfOut,
        mvfaAntiAliasScaleLocation
        ));

    return pVertexBufferBuilder;
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::Builder
//
//  Synopsis:  ctor
//
//-----------------------------------------------------------------------------

fn new(pVertexBuffer: &'y mut CHwTVertexBuffer<'z, TVertex>) -> Self
{
    Self {
    m_pVB: pVertexBuffer,


    //m_rgoPrecomputedTriListVertices: NULL(),
    //m_cPrecomputedTriListVertices: 0,

    //m_rguPrecomputedTriListIndices: NULL(),
    //m_cPrecomputedTriListIndices: 0,

    // These two track the Y extent of the shape this builder is producing.
    m_rCurStratumTop: f32::MAX,
    m_rCurStratumBottom:  -f32::MAX,
    m_fNeedOutsideGeometry: false,
    m_fNeedInsideGeometry: true,

    m_rLastTrapezoidRight: -f32::MAX,
    m_rLastTrapezoidTopRight: -f32::MAX,
    m_rLastTrapezoidBottomRight: -f32::MAX,

    m_fHasFlushed: false,
    //m_map: Default::default(),
    m_rcOutsideBounds: Default::default(),
        #[cfg(debug_assertions)]
        m_mvfDbgOut: MilVertexFormatAttribute::MILVFAttrNone as MilVertexFormat,
        m_mvfIn: MilVertexFormatAttribute::MILVFAttrNone as MilVertexFormat,
        m_mvfGenerated: MilVertexFormatAttribute::MILVFAttrNone  as MilVertexFormat,
        m_mvfaAntiAliasScaleLocation: MilVertexFormatAttribute::MILVFAttrNone,
    }
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::SetupConverter
//
//  Synopsis:  Choose the appropriate conversion method
//

fn SetupConverter(&mut self,
     mvfIn: MilVertexFormat,
     mvfOut: MilVertexFormat,
     mvfaAntiAliasScaleLocation: MilVertexFormatAttribute,
     ) -> HRESULT
{
    let hr = S_OK;

    self.m_mvfIn = mvfIn;

    #[cfg(debug_assertions)]
    {
    self.m_mvfDbgOut = mvfOut;
    }

    self.m_mvfGenerated = mvfOut & !self.m_mvfIn;
    self.m_mvfaAntiAliasScaleLocation = mvfaAntiAliasScaleLocation;

    assert!((self.m_mvfGenerated & MilVertexFormatAttribute::MILVFAttrXY as MilVertexFormat) == 0);

    RRETURN!(hr);
}
}
/* 

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::SetTransformMapping
//
//  Synopsis:  Delegate mapping sets to CHwTVertexMappings
//
//-----------------------------------------------------------------------------

template <class TVertex>
void
CHwTVertexBuffer<TVertex>::Builder::SetTransformMapping(
    __in_ecount(1) const MILMatrix3x2 &mat2DPositionTransform
    )
{
    m_map.SetPositionTransform(mat2DPositionTransform);
}
                                                                    
template <class TVertex>
HRESULT
CHwTVertexBuffer<TVertex>::Builder::SetConstantMapping(
    MilVertexFormatAttribute mvfaLocation,
    __in_ecount(1) const CHwConstantColorSource *pConstCS
    )
{
    HRESULT hr = S_OK;

    IFC(m_map.SetConstantMapping(mvfaLocation, pConstCS));

Cleanup:
    RRETURN(hr);
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::FinalizeMappings
//
//  Synopsis:  Complete setup of vertex mappings
//

template <class TVertex>
HRESULT
CHwTVertexBuffer<TVertex>::Builder::FinalizeMappings(
    )
{
    HRESULT hr = S_OK;

    //
    // Set default Z if required.
    //

    if (m_mvfGenerated & MILVFAttrZ)
    {
        if (!(m_map.m_mvfMapped & MILVFAttrZ))
        {
            m_map.m_vStatic.Z = 0.5f;
        }
    }

    //
    // If AA falloff is not going to scale the diffuse color and it is
    // generated then see if the color is constant such that we can do any
    // complex conversions just once here instead of in every iteration of the
    // expansion loop.  If AA falloff is going to scale the diffuse color then
    // we can still optimize for the falloff = 1.0 case by precomputing that
    // color now and checking for 1.0 during generation.  Such a precomputation
    // has shown significant to performance.
    //

    if (m_mvfGenerated & MILVFAttrDiffuse)
    {
        if (m_map.m_mvfMapped & MILVFAttrDiffuse)
        {

            // Assumes diffuse color is constant
            m_map.m_vStatic.Diffuse =
                Convert_MilColorF_scRGB_To_Premultiplied_MilColorB_sRGB(&m_map.m_colorStatic);
        }
        else
        {
            // Set default Diffuse value: White
            m_map.m_vStatic.Diffuse = MIL_COLOR(0xFF,0xFF,0xFF,0xFF);
        }
    }

    RRETURN(hr);
}*/
impl<TVertex> CHwTVertexBufferBuilder<'_, '_, TVertex> {

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::SetOutsideBounds
//
//
//  Synopsis:  Enables rendering geometry for areas outside the shape but
//             within the bounds.  These areas will be created with
//             zero alpha.
//

pub fn SetOutsideBounds(&mut self,
    prcOutsideBounds: Option<&CMILSurfaceRect>,
    fNeedInside: bool,
    )
{
    // Waffling and outside bounds is not currently implemented.  It's
    // not difficult to do but currently there is no need.
    //assert!(!(self.AreWaffling() && self.prcOutsideBounds));

    if let Some(prcOutsideBounds) = prcOutsideBounds
    {
        self.m_rcOutsideBounds = prcOutsideBounds.clone();
        self.m_fNeedOutsideGeometry = true;
        self.m_fNeedInsideGeometry = fNeedInside;
    }
    else
    {
        self.m_fNeedOutsideGeometry = false;
        self.m_fNeedInsideGeometry = true;
    }
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::BeginBuilding
//
//  Synopsis:  Prepare for a new primitive by resetting the vertex buffer
//
pub fn BeginBuilding(&mut self,
    ) -> HRESULT
{
    
    let hr: HRESULT = S_OK;

    self.m_fHasFlushed = false;
    self.m_pVB.Reset(/*self*/);

    RRETURN!(hr);
}
}
impl IGeometrySink for CHwVertexBufferBuilder<'_, '_> {

    fn AddTrapezoid(&mut self,
        rPixelYTop: f32,              // In: y coordinate of top of trapezoid
        rPixelXTopLeft: f32,          // In: x coordinate for top left
        rPixelXTopRight: f32,         // In: x coordinate for top right
        rPixelYBottom: f32,           // In: y coordinate of bottom of trapezoid
        rPixelXBottomLeft: f32,       // In: x coordinate for bottom left
        rPixelXBottomRight: f32,      // In: x coordinate for bottom right
        rPixelXLeftDelta: f32,        // In: trapezoid expand radius for left edge
        rPixelXRightDelta: f32        // In: trapezoid expand radius for right edge
        ) -> HRESULT
    {
        let hr = S_OK;
    
        if (/*self.AreWaffling()*/ false)
        {
            /*IFC(AddTrapezoidWaffle(
                    rPixelYTop,
                    rPixelXTopLeft,
                    rPixelXTopRight,
                    rPixelYBottom,
                    rPixelXBottomLeft,
                    rPixelXBottomRight,
                    rPixelXLeftDelta,
                    rPixelXRightDelta));*/
        }
        else
        {
            IFC!(self.AddTrapezoidStandard(
                    rPixelYTop,
                    rPixelXTopLeft,
                    rPixelXTopRight,
                    rPixelYBottom,
                    rPixelXBottomLeft,
                    rPixelXBottomRight,
                    rPixelXLeftDelta,
                    rPixelXRightDelta));
        }
    
    //Cleanup:
        RRETURN!(hr);
    }
    

    fn IsEmpty(&self) -> bool {
        self.m_pVB.IsEmpty()
    }

/* 

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::AddVertex
//
//  Synopsis:  Add a vertex to the vertex buffer
//
//             Remember just the given vertex information now and convert later
//             in a single, more optimal pass.
//

template <class TVertex>
HRESULT
CHwTVertexBuffer<TVertex>::Builder::AddVertex(
    __in_ecount(1) const MilPoint2F &ptPosition,
        // Vertex coordinates
    __out_ecount(1) WORD *pIndex
        // The index of the new vertex
    )
{
    HRESULT hr = S_OK;

    Assert(!NeedOutsideGeometry());
    Assert(m_mvfIn == MILVFAttrXY);

    TVertex *pVertex;

    IFC(m_pVB->AddTriListVertices(1, &pVertex, pIndex));

    pVertex->ptPt = ptPosition;

    //  store coverage as a DWORD instead of float

    pVertex->Diffuse = FLOAT_ONE;

Cleanup:
    RRETURN(hr);
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::AddIndexedVertices, IGeometrySink
//
//  Synopsis:  Add a fully computed, indexed vertex to the vertex buffer
//

template <class TVertex>
HRESULT
CHwTVertexBuffer<TVertex>::Builder::AddIndexedVertices(
    UINT cVertices,
        // In: number of vertices                                                       
    __in_bcount(cVertices*uVertexStride) const void *pVertexBufferNoRef,
        // In: vertex buffer containing the vertices                                    
    UINT uVertexStride,
        // In: size of each vertex                                                      
    MilVertexFormat mvfFormat,
        // In: format of each vertex                                                    
    UINT cIndices,
        // In: Number of indices                                                        
    __in_ecount(cIndices) const UINT *puIndexBuffer
        // In: index buffer                                                             
    )
{
    Assert(m_mvfIn & (MILVFAttrXYZ | MILVFAttrDiffuse | MILVFAttrUV2));
    Assert(mvfFormat == (MILVFAttrXYZ | MILVFAttrDiffuse | MILVFAttrUV2));

    Assert(uVertexStride == sizeof(TVertex));

    m_rgoPrecomputedTriListVertices = reinterpret_cast<const TVertex *>(pVertexBufferNoRef);
    m_cPrecomputedTriListVertices = cVertices;

    m_rguPrecomputedTriListIndices = puIndexBuffer;
    m_cPrecomputedTriListIndices = cIndices;

    return S_OK;
}

//+----------------------------------------------------------------------------
//
//  Member:    CHwTVertexBuffer<TVertex>::Builder::AddTriangle
//
//  Synopsis:  Add a triangle to the vertex buffer
//

template <class TVertex>
HRESULT
CHwTVertexBuffer<TVertex>::Builder::AddTriangle(
    DWORD i1,                    // In: Index of triangle's first vertex
    DWORD i2,                    // In: Index of triangle's second vertex
    DWORD i3                     // In: Index of triangle's third vertex
    )
{
    HRESULT hr = S_OK;

    Assert(!NeedOutsideGeometry());

    if (AreWaffling())
    {
        TVertex *pVertex;
        UINT uNumVertices;
        m_pVB->GetTriListVertices(&pVertex, &uNumVertices);

        Assert(i1 < uNumVertices);
        Assert(i2 < uNumVertices);
        Assert(i3 < uNumVertices);

        PointXYA rgPoints[3];
        rgPoints[0].x = pVertex[i1].ptPt.X;
--> --------------------

--> maximum size reached

--> --------------------

[ Verzeichnis aufwärts0.61unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]