// File: /workspace/github_cpp_makefile_star2_O2/YiweiMao[P]tessDX/src/tessellator.cpp
// Function: CHWTessellator::QuadGenerateConnectivity(CHWTessellator::PROCESSED_TESS_FACTORS_QUAD const&)
void CHWTessellator::QuadGenerateConnectivity( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors )
{
    // Generate primitives for all the concentric rings, one side at a time for each ring
    static const int startRing = 1;
    int numPointRowsToCenter[QUAD_AXES] = {((processedTessFactors.numPointsForInsideTessFactor[U]+1) >> 1),
                                            ((processedTessFactors.numPointsForInsideTessFactor[V]+1) >> 1)}; // +1 is so even tess includes the center point
    int numRings = min(numPointRowsToCenter[U],numPointRowsToCenter[V]);
    int degeneratePointRing[QUAD_AXES] = { // Even partitioning causes degenerate row of points,
                                           // which results in exceptions to the point ordering conventions 
                                           // when travelling around the rings counterclockwise.
        (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ? numPointRowsToCenter[V] - 1 : -1,
        (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U]) ? numPointRowsToCenter[U] - 1 : -1 };

    const TESS_FACTOR_CONTEXT* outsideTessFactorCtx[QUAD_EDGES] = {&processedTessFactors.outsideTessFactorCtx[Ueq0],
                                                    &processedTessFactors.outsideTessFactorCtx[Veq0],
                                                    &processedTessFactors.outsideTessFactorCtx[Ueq1],
                                                    &processedTessFactors.outsideTessFactorCtx[Veq1]};
    TESSELLATOR_PARITY outsideTessFactorParity[QUAD_EDGES] = {processedTessFactors.outsideTessFactorParity[Ueq0],
                                                        processedTessFactors.outsideTessFactorParity[Veq0],
                                                        processedTessFactors.outsideTessFactorParity[Ueq1],
                                                        processedTessFactors.outsideTessFactorParity[Veq1]};
    int numPointsForOutsideEdge[QUAD_EDGES] = {processedTessFactors.numPointsForOutsideEdge[Ueq0],
                                              processedTessFactors.numPointsForOutsideEdge[Veq0],
                                              processedTessFactors.numPointsForOutsideEdge[Ueq1],
                                              processedTessFactors.numPointsForOutsideEdge[Veq1]};

    int insideEdgePointBaseOffset = processedTessFactors.insideEdgePointBaseOffset;
    int outsideEdgePointBaseOffset = 0;
    int edge;
    for(int ring = startRing; ring < numRings; ring++)
    {
        int numPointsForInsideEdge[QUAD_AXES] = {processedTessFactors.numPointsForInsideTessFactor[U] - 2*ring,
                                                 processedTessFactors.numPointsForInsideTessFactor[V] - 2*ring};

        int edge0InsidePointBaseOffset = insideEdgePointBaseOffset;
        int edge0OutsidePointBaseOffset = outsideEdgePointBaseOffset;

        for(edge = 0; edge < QUAD_EDGES; edge++ )
        {
            int parity = (edge+1)&0x1;

            int numTriangles = numPointsForInsideEdge[parity] + numPointsForOutsideEdge[edge] - 2;
            int insideBaseOffset;
            int outsideBaseOffset;
            if( edge == 3 ) // We need to patch the indexing so Stitch() can think it sees
                            // 2 sequentially increasing rows of points, even though we have wrapped around
                            // to the end of the inner and outer ring's points, so the last point is really
                            // the first point for the ring.  
                            // We make it so that when Stitch() calls AddIndex(), that function
                            // will do any necessary index adjustment.
            {
                if( ring == degeneratePointRing[parity] )
                {
                    m_IndexPatchContext2.baseIndexToInvert = insideEdgePointBaseOffset + 1;
                    m_IndexPatchContext2.cornerCaseBadValue = outsideEdgePointBaseOffset + numPointsForOutsideEdge[edge] - 1;
                    m_IndexPatchContext2.cornerCaseReplacementValue = edge0OutsidePointBaseOffset;
                    m_IndexPatchContext2.indexInversionEndPoint = (m_IndexPatchContext2.baseIndexToInvert << 1) - 1;
                    insideBaseOffset = m_IndexPatchContext2.baseIndexToInvert;
                    outsideBaseOffset = outsideEdgePointBaseOffset;
                    SetUsingPatchedIndices2(true);
                }
                else
                {
                    m_IndexPatchContext.insidePointIndexDeltaToRealValue    = insideEdgePointBaseOffset;
                    m_IndexPatchContext.insidePointIndexBadValue            = numPointsForInsideEdge[parity] - 1;
                    m_IndexPatchContext.insidePointIndexReplacementValue    = edge0InsidePointBaseOffset;
                    m_IndexPatchContext.outsidePointIndexPatchBase          = m_IndexPatchContext.insidePointIndexBadValue+1; // past inside patched index range
                    m_IndexPatchContext.outsidePointIndexDeltaToRealValue   = outsideEdgePointBaseOffset 
                                                                                - m_IndexPatchContext.outsidePointIndexPatchBase;
                    m_IndexPatchContext.outsidePointIndexBadValue           = m_IndexPatchContext.outsidePointIndexPatchBase
                                                                                + numPointsForOutsideEdge[edge] - 1;
                    m_IndexPatchContext.outsidePointIndexReplacementValue   = edge0OutsidePointBaseOffset;

                    insideBaseOffset = 0;
                    outsideBaseOffset = m_IndexPatchContext.outsidePointIndexPatchBase;
                    SetUsingPatchedIndices(true);
                }
            }
            else if( (edge == 2) && (ring == degeneratePointRing[parity]) )
            {
                m_IndexPatchContext2.baseIndexToInvert = insideEdgePointBaseOffset;
                m_IndexPatchContext2.cornerCaseBadValue = -1; // unused
                m_IndexPatchContext2.cornerCaseReplacementValue = -1; // unused
                m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert << 1;
                insideBaseOffset = m_IndexPatchContext2.baseIndexToInvert;
                outsideBaseOffset = outsideEdgePointBaseOffset;
                SetUsingPatchedIndices2(true);
            }
            else
            {
                insideBaseOffset = insideEdgePointBaseOffset;
                outsideBaseOffset = outsideEdgePointBaseOffset;
            }
            if( ring == startRing )
            {
                StitchTransition(/*baseIndexOffset: */m_NumIndices, 
                               insideBaseOffset,processedTessFactors.insideTessFactorCtx[parity].numHalfTessFactorPoints,processedTessFactors.insideTessFactorParity[parity],
                               outsideBaseOffset,outsideTessFactorCtx[edge]->numHalfTessFactorPoints,outsideTessFactorParity[edge]);
            }
            else
            {
                StitchRegular(/*bTrapezoid*/true, DIAGONALS_MIRRORED,
                              /*baseIndexOffset: */m_NumIndices,
                              numPointsForInsideEdge[parity],
                              insideBaseOffset,outsideBaseOffset);
            }
            SetUsingPatchedIndices(false);
            SetUsingPatchedIndices2(false);
            m_NumIndices += numTriangles*3;
            outsideEdgePointBaseOffset += numPointsForOutsideEdge[edge] - 1;
            if( (edge == 2) && (ring == degeneratePointRing[parity]) )
            {
                insideEdgePointBaseOffset -= numPointsForInsideEdge[parity] - 1;
            }
            else
            {
                insideEdgePointBaseOffset += numPointsForInsideEdge[parity] - 1;
            }
            numPointsForOutsideEdge[edge] = numPointsForInsideEdge[parity];
        }
        if( startRing == ring )
        {
            for(edge = 0; edge < QUAD_EDGES; edge++ )
            {
                outsideTessFactorCtx[edge] = &processedTessFactors.insideTessFactorCtx[edge&1];
                outsideTessFactorParity[edge] = processedTessFactors.insideTessFactorParity[edge&1];
            }
        }
    }

    // Triangulate center - a row of quads if odd
    // This triangulation may be producing diagonals that are asymmetric about 
    // the center of the patch in this region.  
    if( (processedTessFactors.numPointsForInsideTessFactor[U] > processedTessFactors.numPointsForInsideTessFactor[V]) && 
        (TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[V] ) )
    {
        SetUsingPatchedIndices2(true);
        int stripNumQuads = (((processedTessFactors.numPointsForInsideTessFactor[U]>>1) - (processedTessFactors.numPointsForInsideTessFactor[V]>>1))<<1)+
                            ((TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U] ) ? 2 : 1);
        m_IndexPatchContext2.baseIndexToInvert = outsideEdgePointBaseOffset + stripNumQuads + 2;
        m_IndexPatchContext2.cornerCaseBadValue = m_IndexPatchContext2.baseIndexToInvert;
        m_IndexPatchContext2.cornerCaseReplacementValue = outsideEdgePointBaseOffset;
        m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert + 
                                                      m_IndexPatchContext2.baseIndexToInvert + stripNumQuads;
        StitchRegular(/*bTrapezoid*/false,DIAGONALS_INSIDE_TO_OUTSIDE,
                       /*baseIndexOffset: */m_NumIndices, /*numInsideEdgePoints:*/stripNumQuads+1,
                       /*insideEdgePointBaseOffset*/m_IndexPatchContext2.baseIndexToInvert,
                       outsideEdgePointBaseOffset+1);
        SetUsingPatchedIndices2(false);
        m_NumIndices += stripNumQuads*6;
    }
    else if((processedTessFactors.numPointsForInsideTessFactor[V] >= processedTessFactors.numPointsForInsideTessFactor[U]) && 
            (TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[U]) )
    {
        SetUsingPatchedIndices2(true);
        int stripNumQuads = (((processedTessFactors.numPointsForInsideTessFactor[V]>>1) - (processedTessFactors.numPointsForInsideTessFactor[U]>>1))<<1)+
                            ((TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V] ) ? 2 : 1);
        m_IndexPatchContext2.baseIndexToInvert = outsideEdgePointBaseOffset + stripNumQuads + 1;
        m_IndexPatchContext2.cornerCaseBadValue = -1; // unused
        m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert + 
                                                      m_IndexPatchContext2.baseIndexToInvert + stripNumQuads;
		DIAGONALS diag = (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ?  
							DIAGONALS_INSIDE_TO_OUTSIDE : DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE;
        StitchRegular(/*bTrapezoid*/false,diag,
                       /*baseIndexOffset: */m_NumIndices, /*numInsideEdgePoints:*/stripNumQuads+1,
                       /*insideEdgePointBaseOffset*/m_IndexPatchContext2.baseIndexToInvert,
                       outsideEdgePointBaseOffset);
        SetUsingPatchedIndices2(false);
        m_NumIndices += stripNumQuads*6;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq 0xbc(%rsi), %xmm0
pcmpeqd %xmm1, %xmm1
psubd %xmm1, %xmm0
psrad $0x1, %xmm0
movd %xmm0, %eax
pshufd $0x55, %xmm0, %xmm2     # xmm2 = xmm0[1,1,1,1]
movd %xmm2, %ecx
cmpl %ecx, %eax
cmovll %eax, %ecx
movl %ecx, 0x2c(%rsp)
movq %rdi, %r14
movq 0x28(%rsi), %xmm2
pxor %xmm3, %xmm3
pcmpeqd %xmm2, %xmm3
paddd %xmm1, %xmm0
pxor %xmm1, %xmm3
por %xmm0, %xmm3
pshufd $0xe1, %xmm3, %xmm0     # xmm0 = xmm3[1,0,2,3]
movq %xmm0, 0x20(%rsp)
leaq 0x30(%rsi), %rax
movq %rax, 0x80(%rsp)
leaq 0x44(%rsi), %rax
movq %rax, 0x88(%rsp)
leaq 0x58(%rsi), %rax
movq %rax, 0x90(%rsp)
leaq 0x6c(%rsi), %rax
movq %rax, 0x98(%rsp)
movups 0x18(%rsi), %xmm0
movaps %xmm0, 0x70(%rsp)
movdqu 0xac(%rsi), %xmm0
movdqa %xmm0, 0x60(%rsp)
movl 0xc4(%rsi), %eax
movl %eax, 0x14(%rsp)
leaq 0x80(%rsi), %rax
movq %rax, 0x38(%rsp)
movq $0x0, 0x18(%rsp)
pushq $0x1
popq %rax
movl %eax, %r10d
movq %rsi, 0x30(%rsp)
cmpl 0x2c(%rsp), %r10d
jge 0x402cdb
leal (%r10,%r10), %eax
movq 0xbc(%rsi), %xmm0
movd %eax, %xmm1
pshufd $0x50, %xmm1, %xmm1     # xmm1 = xmm1[0,0,1,1]
psubd %xmm1, %xmm0
movq %xmm0, 0x58(%rsp)
pushq $0x1
popq %rbp
movq 0x18(%rsp), %rax
movl %eax, %r8d
movl 0x14(%rsp), %eax
movl %eax, %r11d
cmpq $0x5, %rbp
je 0x402c8e
movl %ebp, %r13d
andl $0x1, %r13d
movl %r13d, %eax
movl 0x58(%rsp,%rax,4), %r12d
movl 0x5c(%rsp,%rbp,4), %edx
leal (%rdx,%r12), %ebx
leal -0x1(%rbp), %ecx
movl %r11d, %eax
movl %r8d, %r9d
cmpl $0x2, %ecx
je 0x402b61
cmpl $0x3, %ecx
jne 0x402bc3
cmpl 0x20(%rsp,%r13,4), %r10d
jne 0x402b86
leal 0x1(%r11), %eax
movl %eax, 0x50(%r14)
leal (%r8,%rdx), %ecx
decl %ecx
movl %ecx, 0x58(%r14)
movq 0x18(%rsp), %rcx
movl %ecx, 0x5c(%r14)
leal 0x1(,%r11,2), %ecx
movl %ecx, 0x54(%r14)
movb $0x1, 0x32(%r14)
jmp 0x402b81
cmpl 0x20(%rsp,%r13,4), %r10d
jne 0x402bc3
movl %r11d, 0x50(%r14)
orq $-0x1, 0x58(%r14)
leal (%r11,%r11), %eax
movl %eax, 0x54(%r14)
movb $0x1, 0x32(%r14)
movl %r11d, %eax
movl %r8d, %r9d
jmp 0x402bc3
movl %r11d, 0x34(%r14)
leal -0x1(%r12), %eax
movl %eax, 0x38(%r14)
movl 0x14(%rsp), %eax
movl %eax, 0x3c(%r14)
movl %r12d, 0x40(%r14)
movl %r8d, %eax
subl %r12d, %eax
movl %eax, 0x44(%r14)
leal -0x1(%rbx), %eax
movl %eax, 0x48(%r14)
movq 0x18(%rsp), %rax
movl %eax, 0x4c(%r14)
movb $0x1, 0x31(%r14)
xorl %eax, %eax
movl %r12d, %r9d
movq %rdx, 0x48(%rsp)
movq %r11, 0x40(%rsp)
movq %r8, 0x50(%rsp)
movl 0x2c(%r14), %ecx
movq %r10, %r15
cmpl $0x1, %r10d
jne 0x402c1b
imulq $0x14, %r13, %rdx
movq 0x38(%rsp), %rsi
movl 0xc(%rsi,%rdx), %r10d
movq 0x30(%rsp), %rdx
movl 0x28(%rdx,%r13,4), %r8d
movq 0x78(%rsp,%rbp,8), %rdx
movl 0xc(%rdx), %edx
movl 0x6c(%rsp,%rbp,4), %esi
movl %esi, 0x8(%rsp)
movl %edx, (%rsp)
movq %r14, %rdi
movl %ecx, %esi
movl %eax, %edx
movl %r10d, %ecx
callq 0x402f7a
jmp 0x402c33
movl %r9d, (%rsp)
movq %r14, %rdi
pushq $0x1
popq %rsi
pushq $0x2
popq %rdx
movl %r12d, %r8d
movl %eax, %r9d
callq 0x40322e
andw $0x0, 0x31(%r14)
leal (%rbx,%rbx,2), %eax
movl 0x2c(%r14), %ecx
addl %ecx, %eax
addl $-0x6, %eax
movl %eax, 0x2c(%r14)
cmpq $0x3, %rbp
movq %r15, %r10
jne 0x402c66
cmpl 0x20(%rsp,%r13,4), %r10d
jne 0x402c66
movq 0x40(%rsp), %r11
subl %r12d, %r11d
incl %r11d
jmp 0x402c71
movq 0x40(%rsp), %r11
addl %r12d, %r11d
decl %r11d
movq 0x50(%rsp), %r8
movq 0x48(%rsp), %rax
addl %eax, %r8d
decl %r8d
movl %r12d, 0x5c(%rsp,%rbp,4)
incq %rbp
jmp 0x402af4
cmpl $0x1, %r10d
movq 0x30(%rsp), %rsi
jne 0x402cc6
xorl %eax, %eax
cmpq $0x4, %rax
je 0x402cc6
movl %eax, %ecx
andl $0x1, %ecx
imulq $0x14, %rcx, %rdx
addq 0x38(%rsp), %rdx
movq %rdx, 0x80(%rsp,%rax,8)
movl %ecx, %ecx
movl 0x28(%rsi,%rcx,4), %ecx
movl %ecx, 0x70(%rsp,%rax,4)
incq %rax
jmp 0x402c9b
incl %r10d
movl %r8d, %eax
movq %rax, 0x18(%rsp)
movl %r11d, 0x14(%rsp)
jmp 0x402ab8
movl 0x2c(%rsi), %ecx
movl 0xbc(%rsi), %edx
movl 0xc0(%rsi), %eax
cmpl %eax, %edx
setg %r8b
cmpl $0x1, %ecx
sete %r9b
testb %r9b, %r8b
je 0x402d58
movb $0x1, 0x32(%r14)
andl $-0x2, %eax
subl %eax, %edx
andl $-0x2, %edx
xorl %eax, %eax
cmpl $0x0, 0x28(%rsi)
sete %al
leal (%rax,%rdx), %ecx
leal 0x1(%rax,%rdx), %ebp
movq 0x18(%rsp), %r10
leal 0x1(%r10,%rcx), %esi
leal 0x3(%r10,%rcx), %r9d
movl %r9d, 0x50(%r14)
movl %r9d, 0x58(%r14)
movl %r10d, 0x5c(%r14)
leal 0x5(%rcx,%rsi,2), %ecx
movl %ecx, 0x54(%r14)
movl 0x2c(%r14), %ecx
leal (%rax,%rdx), %r8d
addl $0x2, %r8d
incl %r10d
movl %r10d, (%rsp)
movq %r14, %rdi
xorl %esi, %esi
xorl %edx, %edx
jmp 0x402db6
cmpl %edx, %eax
jl 0x402dc7
cmpl $0x1, 0x28(%rsi)
jne 0x402dc7
movb $0x1, 0x32(%r14)
andl $-0x2, %edx
subl %edx, %eax
andl $-0x2, %eax
xorl %esi, %esi
xorl %edx, %edx
testl %ecx, %ecx
sete %sil
setne %dl
leal (%rsi,%rax), %ecx
movq 0x18(%rsp), %r10
leal 0x2(%r10,%rcx), %r9d
movl %r9d, 0x50(%r14)
leal (%rcx,%r9,2), %ecx
incl %ecx
movl %ecx, 0x54(%r14)
orl $-0x1, 0x58(%r14)
leal (%rsi,%rax), %ebp
incl %ebp
movl 0x2c(%r14), %ecx
leal (%rsi,%rax), %r8d
addl $0x2, %r8d
movl %r10d, (%rsp)
movq %r14, %rdi
xorl %esi, %esi
callq 0x40322e
movb $0x0, 0x32(%r14)
imull $0x6, %ebp, %eax
addl %eax, 0x2c(%r14)
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop