/*---------------------------------------------------------------------------- accrej.asm - Graphics Trivial Line Accept/Reject ------------------------------------------------------------------------------ Description: Performs trivial accept/reject checking on lines. Input is a list in Data Memory of line endpoint coordinates - a pair of X,Y,Z cordinates for each line. The subroutine performs clipping to a window defined by a list in Program Memory of the Xmin, Xmax, Ymin, Ymax, Zmin, and Zmax coordinates of the viewing volume. This subroutine creates a display list for the line renderer. To do this, each line is classified into one of three categories: trivial acceptance - both endpoints inside view volume, line can be simply rendered trivial rejection - both endpoints outside the view volume, line is not rendered at all neither - the line must be clipped prior to rendering For each line, a value is added to the display list. A zero in the display list represents a trivially rejected line, a one represents a trivially accepted line, and a two indicates the line required clipping. For lines which require clipping, the clipped endpoint values (two points, i.e. 6 values) are written to the clipped endpoint list. When a line requires clipping, the subroutine clipline is called. The clipline procedure is not given here, but clipline can utilize the fact that the endpoints of the unclipped line and the outcodes for those endpoints are available in registers zero through seven. Calling clipline here is preferable to clipping after trivially accepting/rejecting all the lines since the coordinates do not have to be fetched again and the outcodes do not have to be recalculated. After the 6 compares are performed on each point, the Compare Accumulator (upper 6 bits of ASTAT) have these values: OUTCODE bit ASTAT bit Meaning 5 31 Z1 > Zmax 4 30 Z1 < Zmin 3 29 Y1 > Ymax 2 28 Y1 < Ymin 1 27 X1 > Xmax 0 26 X1 < Xmin Thus a point is only in the view volume if all 6 of these bits are zero. Both outcodes must be all zeroes for the line to be trivially accepted. If the logical OR of the outcodes is not equal to all zeroes, the line can be trivially rejected. When the line is neither trivially accepted nor rejected, it is clipped. There will be at least one and at most three bits in the outcode which are non-zero. Each non-zero bit requires the line to be clipped to the window coordinate that bit refers to in the table above. For example, if outcode bit #2 is non-zero, the line must be clipped to the Ymin boundary. clipline should write the value 2 to the display list, and the new endpoints to the clipped endpoint list. DAG1 index register i1 points to the display list, and i2 points to the clipped endpoint list. ------------------------------------------------------------------------------ Program Characteristics: Calling Registers: REGISTER FILE r7 number of lines to be examined r12 preload with 0x3F (six ones) r13 preload with 2 r14 preload with 1 r15 preload with 0 DAG1 (Data Memory) i0 pointer to line endpoint list (X1,Y1,Z1,X2,Y2,Z2,...) m0 +1 i1 pointer to display list i2 pointer to clipped endpoint list DAG2 (Program Memory) i8 pointer to Xmin,Xmax,Ymin,Ymax,Zmin,Zmax l8 6 m8 +1 Registers Altered: r0-r9 Computation Time: = 21*N + 1 best case (all lines trivially accepted, PMDAs in cache) = 25*N + 28 worst case (all lines require clipping, 24 cache misses) where N = number of lines, and worst case does NOT include time to perform clipping = 1.2 million lines classified/second @ 40ns instruction cycle ------------------------------------------------------------------------------ Author: Jim Donahue, Analog Devices DSP Division Revised: 12-SEP-91 ----------------------------------------------------------------------------*/ #include "accrej.h" .SEGMENT /pm pm_code; .GLOBAL accrej; accrej: /* Perform OUTCODE #1 Comparisons */ X1=dm(i0,m0), f8=pm(i8,m8); comp (f8,X1), f8=pm(i8,m8); /* X1 < Xmin ? */ comp (X1,f8), Y1=dm(i0,m0), f8=pm(i8,m8); /* X1 > Xmax ? */ comp (f8,Y1), f8=pm(i8,m8); /* Y1 < Ymin ? */ comp (Y1,f8), Z1=dm(i0,m0), f8=pm(i8,m8); /* Y1 > Ymax ? */ comp (f8,Z1), f8=pm(i8,m8); /* Z1 < Zmin ? */ comp (Z1,f8), X2=dm(i0,m0), f8=pm(i8,m8); /* Z1 > Zmax ? */ /* r7 contains number of lines - decrement it for loop */ r7 = r7 - 1, OC1 = astat; /* get outcode 1, store in a register */ OC1 = fext OC1 by 26:6; /* extract 6 MSBs */ /* START OF LOOP */ lcntr = r7, do arlp-1 until lce; /* Perform OUTCODE #2 Comparisons */ comp (f8,X2), f8=pm(i8,m8); /* X2 < Xmin ? */ comp (X2,f8), Y2=dm(i0,m0), f8=pm(i8,m8); /* X2 > Xmax ? */ comp (f8,Y2), f8=pm(i8,m8); /* Y2 < Ymin ? */ comp (Y2,f8), Z2=dm(i0,m0), f8=pm(i8,m8); /* Y2 > Ymax ? */ comp (f8,Z2), f8=pm(i8,m8); /* Z2 < Zmin ? */ comp (Z2,f8); /* Z2 > Zmax ? */ OC2 = astat; /* get outcode 2, store in a register */ OC2 = fext OC2 by 26:6; /* extract 6 MSBs */ r9 = OC1 and OC2; reject: if ne jump nxt (db); if ne dm(i1,m0) = REJECT; r9 = OC1 or OC2; accept: if eq dm(i1,m0) = ACCEPT; clipit: if ne call clipline; nxt: /* Perform OUTCODE #1 Comparisons */ /* NOTE: Cannot pre-fetch X1 because the old value in X1 must */ /* be preserved until after clipline has been called */ X1=dm(i0,m0), f8=pm(i8,m8); comp (f8,X1), f8=pm(i8,m8); /* X1 < Xmin ? */ comp (X1,f8), Y1=dm(i0,m0), f8=pm(i8,m8); /* X1 > Xmax ? */ comp (f8,Y1), f8=pm(i8,m8); /* Y1 < Ymin ? */ comp (Y1,f8), Z1=dm(i0,m0), f8=pm(i8,m8); /* Y1 > Ymax ? */ comp (f8,Z1), f8=pm(i8,m8); /* Z1 < Zmin ? */ comp (Z1,f8), X2=dm(i0,m0), f8=pm(i8,m8); /* Z1 > Zmax ? */ OC1 = astat; OC1 = fext OC1 by 26:6; arlp: /* END OF LOOP */ comp (f8,X2), f8=pm(i8,m8); /* X2 < Xmin ? */ comp (X2,f8), Y2=dm(i0,m0), f8=pm(i8,m8); /* X2 > Xmax ? */ comp (f8,Y2), f8=pm(i8,m8); /* Y2 < Ymin ? */ comp (Y2,f8), Z2=dm(i0,m0), f8=pm(i8,m8); /* Y2 > Ymax ? */ comp (f8,Z2), f8=pm(i8,m8); /* Z2 < Zmin ? */ comp (Z2,f8); /* Z2 > Zmax ? */ OC2 = astat; OC2 = fext OC2 by 26:6; r9 = OC1 and OC2; rej2: if ne rts (db); if ne dm(i1,m0) = REJECT; r9 = OC1 or OC2; acc2: if eq dm(i1,m0) = ACCEPT; clip2: if ne call clipline; rts; .ENDSEG;