// File: /workspace/github_cpp_makefile_star2_O1/YiweiMao[P]tessDX/src/tessellator.cpp
// Function: CHWTessellator::TriGeneratePoints(CHWTessellator::PROCESSED_TESS_FACTORS_TRI const&)
void CHWTessellator::TriGeneratePoints( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors )
{
    // Generate exterior ring edge points, clockwise starting from point V (VW, the U==0 edge)
    int pointOffset = 0;
    int edge;
    for(edge = 0; edge < TRI_EDGES; edge++ )
    {
        int parity = edge&0x1;
        int startPoint = 0;
        int endPoint = processedTessFactors.numPointsForOutsideEdge[edge] - 1;
        for(int p = startPoint; p < endPoint; p++, pointOffset++) // don't include end, since next edge starts with it.
        {
            FXP fxpParam;
            int q = (parity) ? p : endPoint - p; // whether to reverse point order given we are defining V or U (W implicit):
                                                 // edge0, VW, has V decreasing, so reverse 1D points below
                                                 // edge1, WU, has U increasing, so don't reverse 1D points  below
                                                 // edge2, UV, has U decreasing, so reverse 1D points below
            SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]);
            PlacePointIn1D(processedTessFactors.outsideTessFactorCtx[edge],q,fxpParam);
            if( edge == 0 )
            {
                DefinePoint(/*U*/0,
                            /*V*/fxpParam,
                            /*pointStorageOffset*/pointOffset);
            }
            else
            {
                DefinePoint(/*U*/fxpParam,
                            /*V*/(edge == 2) ? FXP_ONE - fxpParam : 0,
                            /*pointStorageOffset*/pointOffset);
            }
        }
    }

    // Generate interior ring points, clockwise spiralling in
    SetTessellationParity(processedTessFactors.insideTessFactorParity);
    static const int startRing = 1;
    int numRings = (processedTessFactors.numPointsForInsideTessFactor >> 1);
    for(int ring = startRing; ring < numRings; ring++)
    {
        int startPoint = ring;
        int endPoint = processedTessFactors.numPointsForInsideTessFactor - 1 - startPoint;

        for(edge = 0; edge < TRI_EDGES; edge++ )
        {
            int parity = edge&0x1;
            int perpendicularAxisPoint = startPoint;
            FXP fxpPerpParam;
            PlacePointIn1D(processedTessFactors.insideTessFactorCtx,perpendicularAxisPoint,fxpPerpParam);
            fxpPerpParam *= FXP_TWO_THIRDS; // Map location to the right size in barycentric space.
                                         // I (amarp) can draw a picture to explain.
                                         // We know this fixed point math won't over/underflow
            fxpPerpParam = (fxpPerpParam+FXP_ONE_HALF/*round*/)>>FXP_FRACTION_BITS; // get back to n.16
            for(int p = startPoint; p < endPoint; p++, pointOffset++) // don't include end: next edge starts with it. 
            {
                FXP fxpParam;
                int q = (parity) ? p : endPoint - (p - startPoint); // whether to reverse point given we are defining V or U (W implicit):
                                                         // edge0, VW, has V decreasing, so reverse 1D points below
                                                         // edge1, WU, has U increasing, so don't reverse 1D points  below
                                                         // edge2, UV, has U decreasing, so reverse 1D points below
                PlacePointIn1D(processedTessFactors.insideTessFactorCtx,q,fxpParam);
                // edge0 VW, has perpendicular parameter U constant
                // edge1 WU, has perpendicular parameter V constant
                // edge2 UV, has perpendicular parameter W constant 
                const unsigned int deriv = 2; // reciprocal is the rate of change of edge-parallel parameters as they are pushed into the triangle
                switch(edge)
                {
                case 0:
                    DefinePoint(/*U*/fxpPerpParam,
                                /*V*/fxpParam - (fxpPerpParam+1/*round*/)/deriv, // we know this fixed point math won't over/underflow
                                /*pointStorageOffset*/pointOffset);
                    break;
                case 1:
                    DefinePoint(/*U*/fxpParam - (fxpPerpParam+1/*round*/)/deriv,// we know this fixed point math won't over/underflow
                                /*V*/fxpPerpParam,
                                /*pointStorageOffset*/pointOffset);
                    break;
                case 2:
                    DefinePoint(/*U*/fxpParam - (fxpPerpParam+1/*round*/)/deriv,// we know this fixed point math won't over/underflow
                                /*V*/FXP_ONE - (fxpParam - (fxpPerpParam+1/*round*/)/deriv) - fxpPerpParam,// we know this fixed point math won't over/underflow
                                /*pointStorageOffset*/pointOffset);
                    break;
                }
            }
        }
    }
    if( !Odd() )
    {
        // Last point is the point at the center.
        DefinePoint(/*U*/FXP_ONE_THIRD,
                    /*V*/FXP_ONE_THIRD,
                    /*pointStorageOffset*/pointOffset);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdi, %r15
leaq 0x20(%rsi), %rax
movq %rax, 0x10(%rsp)
xorl %r13d, %r13d
xorl %ebx, %ebx
movq %rdi, 0x28(%rsp)
movq %rsi, 0x18(%rsp)
movl 0x74(%rsi,%r13,4), %ebp
cmpl $0x2, %ebp
jl 0x403d66
leaq (,%r13,4), %rax
addq %r13, %rax
movq 0x10(%rsp), %rcx
leaq (%rcx,%rax,4), %r12
movl %ebx, 0x4(%rsp)
movslq %ebx, %rbx
shlq $0x3, %rbx
addq 0x18(%r15), %rbx
movl $0x1, %r14d
subl %ebp, %r14d
decl %ebp
xorl %r15d, %r15d
testb $0x1, %r13b
movl %r15d, %edx
cmovel %ebp, %edx
movq 0x18(%rsp), %rax
movl 0x10(%rax,%r13,4), %eax
movq 0x28(%rsp), %rdi
movl %eax, 0x4(%rdi)
movq %r12, %rsi
leaq 0x44(%rsp), %rcx
callq 0x4031d6
movl 0x44(%rsp), %eax
movl %eax, %ecx
shrl $0x10, %ecx
xorps %xmm1, %xmm1
cvtsi2ss %ecx, %xmm1
movzwl %ax, %ecx
xorps %xmm0, %xmm0
cvtsi2ss %ecx, %xmm0
movss 0xc234b(%rip), %xmm2    # 0x4c603c
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
testq %r13, %r13
je 0x403d35
movl $0x10000, %ecx          # imm = 0x10000
subl %eax, %ecx
cmpq $0x2, %r13
movl $0x0, %eax
cmovnel %eax, %ecx
movzwl %cx, %eax
shrl $0x10, %ecx
xorps %xmm1, %xmm1
cvtsi2ss %ecx, %xmm1
movss %xmm0, (%rbx,%r15,8)
xorps %xmm0, %xmm0
cvtsi2ss %eax, %xmm0
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
jmp 0x403d3d
movl $0x0, (%rbx,%r15,8)
movss %xmm0, 0x4(%rbx,%r15,8)
incq %r15
decl %ebp
movl %r14d, %eax
addl %r15d, %eax
jne 0x403ca6
movl 0x4(%rsp), %ebx
addl %r15d, %ebx
movq 0x28(%rsp), %r15
movq 0x18(%rsp), %rsi
incq %r13
cmpq $0x3, %r13
jne 0x403c67
movl %ebx, 0x4(%rsp)
movl 0x1c(%rsi), %eax
movl %eax, 0x38(%rsp)
movl %eax, 0x4(%r15)
movl 0x80(%rsi), %eax
movl %eax, %ecx
sarl %ecx
movl %ecx, 0x3c(%rsp)
cmpl $0x2, %ecx
jl 0x403fc0
addq $0x5c, %rsi
leal -0x2(%rax), %ecx
movl %ecx, 0x20(%rsp)
leal -0x3(%rax), %ecx
movq %rcx, 0x18(%rsp)
movl $0x1, %r12d
leaq 0xc(%rsp), %r14
movq %rax, 0x48(%rsp)
movl %r12d, %ebx
notl %ebx
addl %eax, %ebx
xorl %ebp, %ebp
movl %ebx, 0x40(%rsp)
movq %r15, %rdi
movq %rsi, %r13
movl %r12d, %edx
movq %r14, %rcx
callq 0x4031d6
imull $0xaaaa, 0xc(%rsp), %ecx # imm = 0xAAAA
addl $0x8000, %ecx           # imm = 0x8000
shrl $0x10, %ecx
movl %ecx, 0xc(%rsp)
cmpl %ebx, %r12d
jge 0x403f95
movq %r12, %r14
leal 0x1(%rcx), %eax
shrl %eax
movl %eax, 0x10(%rsp)
movq 0x18(%r15), %rax
movq %rcx, 0x50(%rsp)
xorps %xmm0, %xmm0
cvtsi2ss %ecx, %xmm0
mulss 0xc2220(%rip), %xmm0    # 0x4c603c
addss 0xc2234(%rip), %xmm0    # 0x4c6058
movss %xmm0, 0x24(%rsp)
movl 0x4(%rsp), %ebx
movslq %ebx, %rbx
leaq (%rax,%rbx,8), %rcx
movq %rcx, 0x30(%rsp)
shlq $0x3, %rbx
addq %rax, %rbx
movl 0x20(%rsp), %r15d
xorl %r12d, %r12d
leal (%r14,%r12), %edx
testb $0x1, %bpl
cmovel %r15d, %edx
movq 0x28(%rsp), %rdi
movq %r13, %rsi
leaq 0x8(%rsp), %rcx
callq 0x4031d6
cmpl $0x2, %ebp
je 0x403efa
cmpl $0x1, %ebp
je 0x403ebd
testl %ebp, %ebp
jne 0x403f69
movl 0x8(%rsp), %eax
subl 0x10(%rsp), %eax
movl %eax, %ecx
shrl $0x10, %ecx
xorps %xmm1, %xmm1
cvtsi2ss %ecx, %xmm1
movzwl %ax, %eax
xorps %xmm0, %xmm0
cvtsi2ss %eax, %xmm0
movss 0x24(%rsp), %xmm2
movq 0x30(%rsp), %rax
movss %xmm2, (%rax,%r12,8)
mulss 0xc2188(%rip), %xmm0    # 0x4c603c
addss %xmm1, %xmm0
jmp 0x403f62
movl 0x8(%rsp), %eax
subl 0x10(%rsp), %eax
movl %eax, %ecx
shrl $0x10, %ecx
xorps %xmm0, %xmm0
cvtsi2ss %ecx, %xmm0
movzwl %ax, %eax
xorps %xmm1, %xmm1
cvtsi2ss %eax, %xmm1
mulss 0xc2159(%rip), %xmm1    # 0x4c603c
addss %xmm0, %xmm1
movq 0x30(%rsp), %rax
movss %xmm1, (%rax,%r12,8)
movss 0x24(%rsp), %xmm0
jmp 0x403f62
movl 0x8(%rsp), %eax
subl 0x10(%rsp), %eax
movq 0x50(%rsp), %rcx
addl %eax, %ecx
movl %eax, %edx
shrl $0x10, %edx
xorps %xmm1, %xmm1
cvtsi2ss %edx, %xmm1
movl $0xffff, %edx           # imm = 0xFFFF
andl %edx, %eax
xorps %xmm2, %xmm2
cvtsi2ss %eax, %xmm2
movl $0x10000, %eax          # imm = 0x10000
subl %ecx, %eax
movss 0xc210a(%rip), %xmm4    # 0x4c603c
mulss %xmm4, %xmm2
movl %eax, %ecx
shrl $0x10, %ecx
xorps %xmm3, %xmm3
cvtsi2ss %ecx, %xmm3
andl %edx, %eax
xorps %xmm0, %xmm0
cvtsi2ss %eax, %xmm0
addss %xmm1, %xmm2
movq 0x30(%rsp), %rax
movss %xmm2, (%rax,%r12,8)
mulss %xmm4, %xmm0
addss %xmm3, %xmm0
movss %xmm0, 0x4(%rbx,%r12,8)
incq %r12
decl %r15d
cmpl %r12d, 0x18(%rsp)
jne 0x403e49
addl %r12d, 0x4(%rsp)
movq 0x28(%rsp), %r15
movq %r13, %rsi
movq %r14, %r12
leaq 0xc(%rsp), %r14
movl 0x40(%rsp), %ebx
jmp 0x403f98
movq %r13, %rsi
incl %ebp
cmpl $0x3, %ebp
jne 0x403dc9
incq %r12
decl 0x20(%rsp)
addq $-0x2, 0x18(%rsp)
cmpl 0x3c(%rsp), %r12d
movq 0x48(%rsp), %rax
jne 0x403dbc
cmpl $0x1, 0x38(%rsp)
je 0x403fde
movq 0x18(%r15), %rax
movslq 0x4(%rsp), %rcx
movabsq $0x3eaaaa003eaaaa00, %rdx # imm = 0x3EAAAA003EAAAA00
movq %rdx, (%rax,%rcx,8)
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop