|
|
1.1 root 1: ;---------------------------Module-Header------------------------------;
2: ; Module Name: fastline.asm
3: ;
4: ; This module goes completely overboard in trying to do fast lines.
5: ; It handles only solid R2_COPYPEN unclipped lines.
6: ;
7: ; Unfortunately, I know of only 4 performance tricks:
8: ;
9: ; 1) Most VGAs can co-process the last write to video memory,
10: ; so we employ a traditional Bresenham-style algorithm (as
11: ; opposed to a run-length version) as this minimizes our
12: ; set-up time, and we can do some work between video writes
13: ; without any throughput penalty.
14: ;
15: ; 2) Most VGAs can do one aligned word write faster than two
16: ; byte writes; consequently we derive a double-stepping DDA
17: ; that does aligned word writes whenever possible (note that
18: ; this only makes sense on x-major lines).
19: ;
20: ; 3) Planar mode can be used to speed up long horizontal lines,
21: ; where the cost to switch from linear to planar mode is offset
22: ; by the ability to light 8 pixels on every word write instead
23: ; of 2.
24: ;
25: ; 4) Most lines have integer end-points, so we accelerate those.
26: ;
27: ; If you're not familiar with GIQ lines, this is not the code to start
28: ; with.
29: ;
30: ; Copyright (c) 1992-1993 Microsoft Corporation
31: ;-----------------------------------------------------------------------;
32:
33: .386
34:
35: .model small,c
36:
37: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
38: assume fs:nothing,gs:nothing
39:
40: .xlist
41: include stdcall.inc ;calling convention cmacros
42: include i386\egavga.inc
43: include i386\strucs.inc
44: include i386\driver.inc
45: include i386\lines.inc
46: .list
47:
48: ; Length of horizontal line needed before we'll do it in planar mode:
49:
50: NUM_PELS_NEEDED_FOR_PLANAR_HORIZONTAL equ 64
51:
52: ; Line coordinates are given in 28.4 fixed point format:
53:
54: F equ 16
55: FLOG2 equ 4
56:
57: ; The following values must match those in winddi.h!
58:
59: PD_BEGINSUBPATH equ 00000001h
60: PD_ENDSUBPATH equ 00000002h
61: PD_RESETSTYLE equ 00000004h
62: PD_CLOSEFIGURE equ 00000008h
63: PD_BEZIERS equ 00000010h
64:
65: PATHDATA struc
66:
67: pd_flags dd ?
68: pd_count dd ?
69: pd_pptfx dd ?
70:
71: PATHDATA ends
72:
73: ;-------------------------------------------------------------------------;
74: ; I felt a compelling need to use 'ebp' as a 7th general register, and we
75: ; have no nifty macros for dereferencing frame variables off 'esp'. So
76: ; with this structure I am rolling my own stack frame:
77:
78: STATE_MEM_SIZE equ 4 ;4 dwords
79: PROC_MEM_SIZE equ 6 ;6 dwords
80:
81: STACK_FRAME struc
82:
83: ; State variables (don't add/delete fields without modifying STATE_MEM_SIZE!)
84:
85: sf_ulOurEbp dd ? ;useful for debugging
86: sf_ulOriginalEbx dd ?
87: sf_ulOriginalEdi dd ?
88: sf_ulOriginalEsi dd ?
89:
90: ; Frame variables (feel free to add/delete fields):
91:
92: sf_lDelta dd ? ;sign depends on going up or down
93: sf_pfnReturn dd ? ;where to jump after getting next bank
94: sf_pfnNextBank dd ? ;routine for getting the next bank
95: sf_y0 dd ? ;GIQ variables
96: sf_y1 dd ?
97: sf_x1 dd ?
98: sf_pjStart dd ? ;for remembering edi
99: sf_cAfterThisBank dd ? ;# of pixels to light after this bank
100: sf_ptlOrg db (size POINTL) dup (?)
101: ;our origin for normalizing the line
102: sf_ptfxLast db (size POINTL) dup (?)
103: ;the most recent point
104: sf_ptfxStartFigure db (size POINTL) dup (?)
105: ;the figure's 1st point
106: sf_bMore dd ? ;more path records to get?
107: sf_pptfxEnd dd ? ;points to last point in record
108: sf_pptfx dd ? ;points to current point
109: sf_pd db (size PATHDATA) dup (?)
110: ;pathdata structure
111:
112: ; Procedure variables (don't add/delete fields without modifying
113: ; PROC_MEM_SIZE!)
114:
115: sf_ulOriginalEbp dd ?
116: sf_ulOriginalReturn dd ?
117: sf_ppdev dd ?
118: sf_ppo dd ?
119: sf_lNextScan dd ?
120: sf_iColor dd ?
121:
122: STACK_FRAME ends
123:
124: .data
125:
126: EXTRNP PATHOBJ_bEnum,8
127:
128: .code
129:
130: ROUND_X_DOWN equ 01h
131: ROUND_Y_DOWN equ 02h
132: ROUND_SLOPE_ONE equ 04h
133: ROUND_X_AND_Y_DOWN equ (ROUND_X_DOWN + ROUND_Y_DOWN)
134: ROUND_X_DOWN_SLOPE_ONE equ (ROUND_X_DOWN + ROUND_SLOPE_ONE)
135: ROUND_Y_DOWN_SLOPE_ONE equ (ROUND_Y_DOWN + ROUND_SLOPE_ONE)
136:
137: ;--------------------------------Macro----------------------------------;
138: ; GIQ flags
139: ;
140: ; This macros computes the start pixel, the number of pixels to
141: ; be lit, and the initial error term given a GIQ line. The line must
142: ; have already been normalized such that dM >= dN, dN >= 0.
143: ;
144: ; Input: eax - M0
145: ; ebx - N0
146: ; ecx - dM
147: ; edx - dN
148: ; Trashes:
149: ; esi, ebp
150: ; [esp].sf_ptlOrg.ptl_x, [esp].sf_ptlOrg.ptl_y
151: ; Output:
152: ; [esp].sf_x1 - x-coordinate of last pixel (exclusive)
153: ; eax - x-coordinate of first pixel
154: ; ebx - error term
155: ; ecx - dM
156: ; edx - dN
157: ; edi - y-coordinate of first pixel
158: ;-----------------------------------------------------------------------;
159:
160: GIQ macro flags
161: local compute_x1, compute_error_term
162:
163: ; We normalize our coordinate system so that if the start point is
164: ; (M0/F, N0/F), the origin is at (floor(M0/F), (N0/F)):
165:
166: mov esi,eax
167: mov edi,ebx
168: sar esi,FLOG2
169: sar edi,FLOG2
170: mov [esp].sf_ptlOrg.ptl_x,esi
171: ;ptlOrg.x = floor(M0 / F)
172: mov [esp].sf_ptlOrg.ptl_y,edi
173: ;ptlOrg.y = floor(N0 / F)
174:
175: ; Calculate the correct [esp].sf_x1:
176:
177: lea edi,[ebx + edx] ;edi = N1
178: and edi,F - 1
179:
180: if (flags AND ROUND_X_DOWN)
181:
182: if (flags AND ROUND_SLOPE_ONE)
183: lea ebp,[eax + ecx]
184: and ebp,F - 1 ;ebp = M1
185: sub ebp,8
186: cmp ebp,edi ;cmp M1 - 8, N1
187: jne short compute_x1
188:
189: lea ebp,[eax + ecx]
190: sar ebp,FLOG2
191: jmp short compute_error_term
192: endif
193:
194: compute_x1:
195:
196: cmp edi,1
197: sbb edi,8 ;N1 -= 8
198: else
199: sub edi,8 ;N1 -= 8
200: endif
201: sbb esi,esi
202: xor edi,esi
203: sub edi,esi ;N1 = ABS(N1)
204:
205: lea ebp,[eax + ecx]
206: mov esi,ebp
207: sar ebp,FLOG2
208: and esi,F - 1
209: jz short @f ;special case for M1 == 0
210: cmp esi,edi ;cmp M1, N1
211: sbb ebp,-1 ;ebp is now one pixel past the actual
212: @@: ; end coordinate (note that it hasn't
213: ; been affected by the origin shift)
214:
215: compute_error_term:
216:
217: ; eax = M0
218: ; ebx = N0
219: ; ebp = x1
220: ; ecx = dM
221: ; edx = dN
222:
223: and ebx,F - 1
224: mov [esp].sf_x1,ebp ;save x1
225:
226: ; Calculate our error term for x = 0.
227: ;
228: ; NOTE: Since this routine is used only for lines that are unclipped, we
229: ; are guaranteed by our screen size that the values will be far less
230: ; than 32 bits in significance, and so we don't worry about overflow.
231: ; If this is used for clipped lines, these multiplies will have to
232: ; be converted to give 64 bit results, because we can have 36 bits of
233: ; significance!
234:
235:
236: lea edi,[ebx + 8] ;edi = N0 + 8
237: mov esi,ecx
238: imul esi,edi ;esi = dM * (N0 + 8)
239: mov edi,edx
240:
241: ; We have to special case when M0 is 0 -- we know x0 will be zero.
242: ; So we jump ahead a bit to a place where 'eax' is assumed to contain
243: ; x0 -- and it just so happens 'eax' is zero in this case:
244:
245: and eax,F - 1
246: jz short @f
247: imul edi,eax ;edi = dN * M0
248: sub esi,edi
249:
250: ; Calculate the x-coordinate of the first pixel:
251:
252: if (flags AND ROUND_X_DOWN)
253:
254: if (flags AND ROUND_SLOPE_ONE)
255: cmp ebx,8
256: sbb ebx,-1
257: endif
258:
259: cmp ebx,1
260: sbb ebx,8 ;N0 -= 8
261: else
262: sub ebx,8 ;N0 -= 8
263: endif
264: sbb edi,edi
265: xor ebx,edi
266: sub ebx,edi ;N0 = ABS(N0)
267: cmp eax,ebx
268: sbb eax,eax
269: not eax ;eax = -x0
270:
271: ; Now adjust the error term accordingly:
272:
273: @@:
274: if (flags AND ROUND_Y_DOWN)
275: dec esi
276: endif
277: sar esi,FLOG2 ;esi = floor((N0 + 8) dM - M0 dN] / 16)
278:
279: mov ebx,[esp].sf_ptlOrg.ptl_x
280: mov edi,[esp].sf_ptlOrg.ptl_y
281:
282: sub ebx,eax ;ebx = ptlOrg.ptl_x + x0
283:
284: and eax,edx
285: add eax,esi
286: sub eax,ecx ;eax = dN * x0 + initial error - dM
287: jl short @f ;if the error term >= 0, we have to
288: sub eax,ecx ; add 1 to the y position and subtract
289: inc edi ; dM off again
290: @@:
291: xchg eax,ebx
292:
293: endm
294:
295: ;--------------------------------Macro----------------------------------;
296: ; GIQR flags
297: ;
298: ; Same as above, except it handles flips about the line x = y.
299: ;
300: ; Input: eax - M0
301: ; ebx - N0
302: ; ecx - dM
303: ; edx - dN
304: ; Trashes:
305: ; esi, ebp
306: ; [esp].sf_ptlOrg.ptl_x, [esp].sf_ptlOrg.ptl_y
307: ; Output:
308: ; [esp].sf_y1 - y-coordinate of last pixel (exclusive)
309: ; eax - x-coordinate of first pixel
310: ; ebx - error term
311: ; ecx - dM
312: ; edx - dN
313: ; edi - y-coordinate of first pixel
314: ;-----------------------------------------------------------------------;
315:
316: GIQR macro flags
317:
318: ; We normalize our coordinate system so that if the start point is
319: ; (M0/F, N0/F), the origin is at (floor(M0/F), (N0/F)):
320:
321: mov esi,eax
322: mov edi,ebx
323: sar esi,FLOG2
324: sar edi,FLOG2
325: mov [esp].sf_ptlOrg.ptl_x,esi
326: ;ptlOrg.x = floor(M0 / F)
327: mov [esp].sf_ptlOrg.ptl_y,edi
328: ;ptlOrg.y = floor(N0 / F)
329:
330: ; Calculate the correct [esp].sf_y1:
331:
332: lea edi,[eax + ecx] ;edi = M1
333: and edi,F - 1
334:
335: if (flags AND ROUND_Y_DOWN)
336: cmp edi,1
337: sbb edi,8 ;M1 -= 8
338: else
339: sub edi,8 ;M1 -= 8
340: endif
341: sbb esi,esi
342: xor edi,esi
343: sub edi,esi ;M1 = ABS(M1)
344:
345: lea ebp,[ebx + edx]
346: mov esi,ebp
347: sar ebp,FLOG2
348: and esi,F - 1
349: jz short @f ;special case for N1 == 0
350: cmp esi,edi ;cmp N1, M1
351: sbb ebp,-1 ;ebp is now one pixel past the actual
352: @@: ; end coordinate (note that it hasn't
353: ; been affected by the origin shift)
354: and eax,F - 1
355: mov [esp].sf_y1,ebp
356:
357: ; Calculate our error term for y = 0.
358: ;
359: ; NOTE: Since this routine is used only for lines that are unclipped, we
360: ; are guaranteed by our screen size that the values will be far less
361: ; than 32 bits in significance, and so we don't worry about overflow.
362: ; If this is used for clipped lines, these multiplies will have to
363: ; be converted to give 64 bit results, because we can have 36 bits of
364: ; significance!
365:
366: lea edi,[eax + 8] ;edi = M0 + 8
367: mov esi,edx
368: imul esi,edi ;esi = dN * (M0 + 8)
369: mov edi,ecx
370:
371: ; We have to special case when N0 is 0 -- we know y0 will be zero.
372: ; So we jump ahead a bit to a place where 'ebx' is assumed to contain
373: ; y0 -- and it just so happens 'ebx' is zero in this case:
374:
375: and ebx,F - 1
376: jz short @f
377: imul edi,ebx ;edi = dM * N0
378: sub esi,edi
379:
380: ; Calculate the x-coordinate of the first pixel:
381:
382: if (flags AND ROUND_Y_DOWN)
383: cmp eax,1
384: sbb eax,8 ;M0 -= 8
385: else
386: sub eax,8 ;M0 -= 8
387: endif
388: sbb edi,edi
389: xor eax,edi
390: sub eax,edi ;M0 = ABS(M0)
391: cmp ebx,eax
392: sbb ebx,ebx
393: not ebx ;ebx = -y0
394:
395: ; Now adjust the error term accordingly:
396:
397: @@:
398: if (flags AND ROUND_X_DOWN)
399: dec esi
400: endif
401: sar esi,FLOG2 ;esi = floor((M0 + 8) dN - N0 dM] / 16)
402:
403: mov eax,[esp].sf_ptlOrg.ptl_x
404: mov edi,[esp].sf_ptlOrg.ptl_y
405:
406: sub edi,ebx ;edi = ptlOrg.ptl_y + y0
407:
408: and ebx,ecx
409: add ebx,esi
410: sub ebx,edx ;ebx = dM * x0 + initial error - dN
411: jl short @f ;if the error term >= 0, we have to
412: sub ebx,edx ; add 1 to the x position and subtract
413: inc eax ; dN off again
414: @@:
415:
416: endm
417:
418: ;---------------------------Public-Routine------------------------------;
419: ; vFastLine(ppdev, ppo, lNextScan, iColor)
420: ;
421: ; Draws fast lines. Or at least attempts to.
422: ;
423: ; Input:
424: ;
425: ; ppdev - PDEV pointer
426: ; ppo - path
427: ; lNextScan - delta to start of next scan (same as ppdev->lNextScan)
428: ; iColor - color (least significant byte must be the same as the next
429: ; least signficant byte, so that we can do words writes)
430: ;
431: ;-----------------------------------------------------------------------;
432:
433: ; NOTE: Don't go changing parameters without also changing STACK_FRAME!
434:
435: cProc vFastLine,16,< \
436: uses esi edi ebx, \
437: ebp_ppdev: ptr, \
438: ebp_ppo: ptr, \
439: ebp_lNextScan: ptr, \
440: ebp_iColor: dword >
441:
442: ; Leave room for our stack frame.
443: ;
444: ; NOTE: Don't add local variables here -- you can't reference them with
445: ; ebp anyway! Add them to the STACK_FRAME structure.
446:
447: local aj[(size STACK_FRAME) - 4 * (STATE_MEM_SIZE + PROC_MEM_SIZE)]: byte
448:
449: ; We save 'ebp' on the stack (note that STACK_FRAME accounts for this push):
450:
451: push ebp
452:
453: ; Now get some path stuff:
454:
455: next_record:
456:
457: mov esi,[esp].sf_ppo
458: lea eax,[esp].sf_pd
459: cCall PATHOBJ_bEnum,<esi,eax>
460: mov [esp].sf_bMore,eax ;save away return code for later
461:
462: mov eax,[esp].sf_pd.pd_count;if 0 points in record, get outta here
463: or eax,eax
464: jz check_for_closefigure
465:
466: lea edi,[8 * eax - 8]
467: add edi,[esp].sf_pd.pd_pptfx
468: mov [esp].sf_pptfxEnd,edi ;points to last point in record
469:
470: mov ebx,[esp].sf_pd.pd_flags
471: test ebx,PD_BEGINSUBPATH
472: jz short continue_subpath
473:
474: ; Handle a new sub-path:
475:
476: mov esi,[esp].sf_pd.pd_pptfx
477: add esi,8
478: mov [esp].sf_pptfx,esi
479:
480: mov ecx,[edi].ptl_x ;remember last point in case we have
481: mov edx,[edi].ptl_y ; to continue to another record
482: mov [esp].sf_ptfxLast.ptl_x,ecx
483: mov [esp].sf_ptfxLast.ptl_y,edx
484:
485: mov eax,[esi - 8].ptl_x ;load up current start and end point
486: mov ebx,[esi - 8].ptl_y
487: mov ecx,[esi].ptl_x
488: mov edx,[esi].ptl_y
489: mov [esp].sf_ptfxStartFigure.ptl_x,eax
490: mov [esp].sf_ptfxStartFigure.ptl_y,ebx
491:
492: cmp esi,[esp].sf_pptfxEnd ;we have to be careful when the only
493: ; point in the record is the start-
494: ; figure point (pretty rare)
495: jbe new_line
496: jmp short next_record
497:
498: continue_subpath:
499:
500: ; This record continues the path:
501:
502: mov esi,[esp].sf_pd.pd_pptfx
503: mov eax,[esp].sf_ptfxLast.ptl_x ;load up current start point
504: mov ebx,[esp].sf_ptfxLast.ptl_y
505:
506: mov ecx,[edi].ptl_x ;remember last point in case we have
507: mov edx,[edi].ptl_y ; to continue to another record
508: mov [esp].sf_ptfxLast.ptl_x,ecx
509: mov [esp].sf_ptfxLast.ptl_y,edx
510:
511: mov ecx,[esi].ptl_x ;load up current end point
512: mov edx,[esi].ptl_y
513: mov [esp].sf_pptfx,esi
514: jmp short new_line
515:
516: ;/////////////////////////////////////////////////////////////////////
517: ;// Next Line Stuff
518: ;/////////////////////////////////////////////////////////////////////
519:
520: handle_closefigure:
521: mov [esp].sf_pd.pd_flags,0
522: mov eax,[esp].sf_ptfxLast.ptl_x
523: mov ebx,[esp].sf_ptfxLast.ptl_y
524: mov ecx,[esp].sf_ptfxStartFigure.ptl_x
525: mov edx,[esp].sf_ptfxStartFigure.ptl_y
526: jmp new_line
527:
528: ; Before getting the next path record, see if we have to do a closefigure:
529:
530: check_for_closefigure:
531: test [esp].sf_pd.pd_flags,PD_CLOSEFIGURE
532: jnz handle_closefigure
533: mov ecx,[esp].sf_bMore
534: or ecx,ecx
535: jnz next_record
536:
537: all_done:
538:
539: pop ebp
540: cRet vFastLine
541:
542: public next_line
543: next_line:
544: mov esi,[esp].sf_pptfx
545: cmp esi,[esp].sf_pptfxEnd
546: jae short check_for_closefigure
547:
548: mov eax,[esi].ptl_x
549: mov ebx,[esi].ptl_y
550: mov ecx,[esi+8].ptl_x
551: mov edx,[esi+8].ptl_y
552: add esi,8
553: mov [esp].sf_pptfx,esi
554:
555: ;/////////////////////////////////////////////////////////////////////
556: ;// Main Loop
557: ;/////////////////////////////////////////////////////////////////////
558:
559: public new_line
560: new_line:
561:
562: ; Octants are numbered as follows:
563: ;
564: ; \ 5 | 6 /
565: ; \ | /
566: ; 4 \ | / 7
567: ; \ /
568: ; -----+-----
569: ; /|\
570: ; 3 / | \ 0
571: ; / | \
572: ; / 2 | 1 \
573: ;
574:
575: ; eax = M0
576: ; ebx = N0
577: ; ecx = M1 (dM)
578: ; edx = N1 (dN)
579:
580: sub ecx,eax
581: jl octants_2_3_4_5
582: sub edx,ebx
583: jl octants_6_7
584: cmp ecx,edx
585: jl octant_1
586:
587: ;/////////////////////////////////////////////////////////////////////
588: ;// Octant 0
589: ;/////////////////////////////////////////////////////////////////////
590:
591: public octant_0
592: octant_0:
593: mov esi,[esp].sf_lNextScan
594: mov [esp].sf_lDelta,esi ;we're going down
595: mov [esp].sf_pfnNextBank,offset bank_x_major_next_lower
596:
597: mov esi,ecx
598: or esi,edx
599: jz next_line ;we do an early check here for
600: ; lines that start and end on the
601: ; same GIQ point, because those
602: ; occur surprisingly often.
603: or esi,eax
604: or esi,ebx
605: and esi,F - 1
606: jnz oct_0_non_integer
607:
608: or edx,edx
609: jz do_horizontal_line
610:
611: mov esi,[esp].sf_ppdev
612: sar eax,FLOG2 ;x0
613: sar ebx,FLOG2 ;y0
614:
615: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
616: jl short oct_0_map_in_bank
617:
618: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
619: jl short oct_0_done_bank_map
620:
621: oct_0_map_in_bank:
622: push eax
623: push ecx
624: push edx
625:
626: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
627:
628: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
629: <esi, ebx, JustifyTop> ;###
630:
631: pop edx
632: pop ecx
633: pop eax
634:
635: public oct_0_done_bank_map
636: oct_0_done_bank_map:
637: mov edi,[esp].sf_lNextScan
638: imul edi,ebx
639: add edi,[esi].pdev_pvBitmapStart
640: add edi,eax ;edi now points to start byte
641:
642: mov ebp,[esi].pdev_rcl1WindowClip.yBottom
643: sub ebp,ebx ;### ebp = # of scans before end of bank
644:
645: mov esi,ecx
646: sar esi,FLOG2 ;esi = # of pixels to lay down
647:
648: mov ebx,-1 ;### round y = 1/2 *DOWN* in value
649: sub ebx,ecx
650: sar ebx,1 ;now have error term
651:
652: mov eax,[esp].sf_iColor
653: sub ecx,edx ;ecx = dM - dN
654: cmp edx,ecx
655: jg oct_07b
656:
657: ;-------------------------------------------------------------------------;
658: ; Left-to-right Lines With ABS(Slope) <= 1/2
659: ; ------------------------------------------
660: ;
661: ; Since the line's slope is less than 1/2, we have only 3 possibilities
662: ; at each pair of pixels:
663: ;
664: ; Case 1: o Case 2: o o Case 3: o o o
665: ; o o o
666: ;
667: ; Case: err + dN >= 0 err + 2dN >= 0 err + 2dN < 0
668: ; New: err += 2dN - dM err += 2dN - dM err += 2dN
669: ;
670: ; eax = color
671: ; ebx = error term
672: ; ecx = dM - dN
673: ; edx = dN
674: ; esi = # of pixels to lay down
675: ; edi = memory pointer
676: ; ebp = # of scans before end of bank
677: ;-------------------------------------------------------------------------;
678:
679: public oct_07a
680: oct_07a:
681: test edi,1
682: jz short oct_07a_main ;start is word aligned
683:
684: ; Handle unaligned start:
685:
686: dec esi
687: jl next_line
688:
689: mov [edi],al
690: inc edi
691: add ebx,edx ;err += dN
692: jl short oct_07a_main
693:
694: add edi,[esp].sf_lDelta
695: dec ebp ;hit a new bank?
696: jz short oct_07a_next_bank_3
697: oct_07a_done_bank_3:
698: sub ebx,ecx ;err += dN - dM
699: jl short oct_07a_continue
700:
701: ;;; Case 1:
702:
703: public oct_07a_case_1
704: oct_07a_case_1:
705: sub esi,2
706: jl short oct_07a_done
707: mov [edi],al
708: add edi,[esp].sf_lDelta
709: add edi,2
710: dec ebp
711: jz short oct_07a_next_bank_1
712: oct_07a_done_bank_1:
713: mov [edi-1],al
714: sub ebx,ecx ;err += dN - dM
715: ;;;case 1 is done
716: ;;; Main loop:
717:
718: oct_07a_main:
719: add ebx,edx ;err += dN
720: jge short oct_07a_case_1
721: oct_07a_continue:
722: sub esi,2
723: jl short oct_07a_done
724: mov [edi],ax
725: add edi,2
726: add ebx,edx ;err += dN
727: jl short oct_07a_main ;;;case 3 is done
728:
729: ;;; Handle end of case 2:
730:
731: add edi,[esp].sf_lDelta
732: dec ebp
733: jz short oct_07a_next_bank_2
734: oct_07a_done_bank_2:
735: sub ebx,ecx ;err += dN - dM
736: jge short oct_07a_case_1
737: jmp short oct_07a_continue ;;;case 2 is done
738:
739: oct_07a_done:
740: inc esi ;esi = -1 means do another pixel
741: jnz next_line
742: mov [edi],al
743: jmp next_line
744:
745: oct_07a_next_bank_1:
746: mov [esp].sf_pfnReturn,offset oct_07a_done_bank_1
747: jmp [esp].sf_pfnNextBank
748: oct_07a_next_bank_2:
749: mov [esp].sf_pfnReturn,offset oct_07a_done_bank_2
750: jmp [esp].sf_pfnNextBank
751: oct_07a_next_bank_3:
752: mov [esp].sf_pfnReturn,offset oct_07a_done_bank_3
753: jmp [esp].sf_pfnNextBank
754:
755: ;-------------------------------------------------------------------------;
756: ; Left-to-right Lines With 1/2 < ABS(Slope) <= 1
757: ; ----------------------------------------------
758: ;
759: ; Since the line's slope is between 1/2 and 1, we have only 3 possibilities
760: ; at each pair of pixels:
761: ;
762: ; Case 1: o o Case 2: o Case 3: o
763: ; o o o o
764: ; o
765: ;
766: ; Case: err + dN < 0 err + 2dN - dM < 0 err + 2dN - dM >= 0
767: ; New: err += 2dN - dM err += 2dN - dM err += 2dN - 2dM
768: ;
769: ; eax = color
770: ; ebx = error term
771: ; ecx = dM - dN
772: ; edx = dN
773: ; esi = # of pixels to lay down
774: ; edi = memory pointer
775: ; ebp = # of scans before end of bank
776: ;-------------------------------------------------------------------------;
777:
778: public oct_07b
779: oct_07b:
780: test edi,1
781: jz short oct_07b_main
782:
783: dec esi
784: jl next_line
785:
786: mov [edi],al
787: inc edi
788: add ebx,edx ;err += dN
789: jl short oct_07b_main
790:
791: add edi,[esp].sf_lDelta
792: dec ebp
793: jz short oct_07b_next_bank_4
794: oct_07b_done_bank_4:
795: sub ebx,ecx ;err += dN - dM
796: jge short oct_07b_continue
797:
798: public oct_07b_case_1
799: oct_07b_case_1:
800: sub esi,2
801: jl short oct_07b_done
802: mov [edi],ax
803: add edi,[esp].sf_lDelta
804: add edi,2
805: dec ebp
806: jz short oct_07b_next_bank_1
807: oct_07b_done_bank_1:
808: sub ebx,ecx ;err += dN - dM
809: ;;;case 1 is done
810: ;;; Main loop:
811:
812: oct_07b_main:
813: add ebx,edx ;err += dN
814: jl short oct_07b_case_1
815: oct_07b_continue:
816: sub esi,2
817: jl short oct_07b_done
818: mov [edi],al
819: add edi,[esp].sf_lDelta
820: add edi,2
821: dec ebp
822: jz short oct_07b_next_bank_2
823: oct_07b_done_bank_2:
824: mov [edi-1],al
825: sub ebx,ecx ;err += dN - dM
826: jl short oct_07b_main ;;;case 2 is done
827:
828: add edi,[esp].sf_lDelta
829: dec ebp
830: jz oct_07b_next_bank_3
831: oct_07b_done_bank_3:
832: sub ebx,ecx ;err += dN - dM
833: jl short oct_07b_case_1 ;;;case 3 is done
834: jmp short oct_07b_continue
835:
836: oct_07b_next_bank_4:
837: mov [esp].sf_pfnReturn,offset oct_07b_done_bank_4
838: jmp [esp].sf_pfnNextBank
839: oct_07b_next_bank_3:
840: mov [esp].sf_pfnReturn,offset oct_07b_done_bank_3
841: jmp [esp].sf_pfnNextBank
842: oct_07b_next_bank_2:
843: mov [esp].sf_pfnReturn,offset oct_07b_done_bank_2
844: jmp [esp].sf_pfnNextBank
845: oct_07b_next_bank_1:
846: mov [esp].sf_pfnReturn,offset oct_07b_done_bank_1
847: jmp [esp].sf_pfnNextBank
848:
849: oct_07b_done:
850: inc esi
851: jnz next_line ;esi = -1 means do another pixel
852: mov [edi],al
853: jmp next_line
854:
855: ;-------------------------------------------------------------------------;
856:
857: public oct_0_non_integer
858: oct_0_non_integer:
859: cmp ecx,edx
860: je oct_0_slope_one ;have a special case rounding rule for
861: ; 45 degree lines (which only affects
862: ; non-integer lines)
863:
864: GIQ ROUND_X_AND_Y_DOWN ;### round x=1/2, y=1/2 down in value
865:
866: or edx,edx
867: jz do_non_integer_horizontal_line
868:
869: oct_0_common:
870: mov esi,[esp].sf_ppdev
871: cmp edi,[esi].pdev_rcl1WindowClip.yTop
872: jl short oct_0_nonint_map_in_bank
873:
874: cmp edi,[esi].pdev_rcl1WindowClip.yBottom
875: jl short oct_0_nonint_done_bank_map
876:
877: oct_0_nonint_map_in_bank:
878: push eax
879: push ecx
880: push edx
881:
882: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
883: <esi, edi, JustifyTop> ;###
884:
885: pop edx
886: pop ecx
887: pop eax
888:
889: oct_0_nonint_done_bank_map:
890: mov ebp,[esi].pdev_rcl1WindowClip.yBottom
891: sub ebp,edi ;### ebp = # scans before end of bank
892:
893: imul edi,[esp].sf_lNextScan ;
894: add edi,[esi].pdev_pvBitmapStart
895: add edi,eax ;edi now points to start byte
896:
897: mov esi,[esp].sf_x1
898: sub esi,eax ;esi = # pixels to lay down
899:
900: mov eax,[esp].sf_iColor
901:
902: sub ecx,edx ;ecx = dM - dN
903: cmp edx,ecx
904: jg oct_07b
905: jmp oct_07a
906:
907: ;-------------------------------------------------------------------;
908: ; 45 degree lines have a special rounding rule: when the line
909: ; runs exactly half way between to pixels, the upper or right pel
910: ; is illuminated. This translates into x=1/2 rounding up, and
911: ; y=1/2 rounding down in value:
912:
913: public oct_0_slope_one
914: oct_0_slope_one:
915: GIQ ROUND_Y_DOWN_SLOPE_ONE ;round y=1/2 down in value
916: jmp oct_0_common
917:
918: ;/////////////////////////////////////////////////////////////////////
919: ;// Octant 1
920: ;/////////////////////////////////////////////////////////////////////
921:
922: public octant_1
923: octant_1:
924: mov [esp].sf_pfnNextBank,offset bank_y_major_next_lower
925:
926: mov esi,eax
927: or esi,ebx
928: or esi,ecx
929: or esi,edx
930: and esi,F - 1
931: jnz oct_1_non_integer
932:
933: mov esi,[esp].sf_ppdev
934: sar eax,FLOG2 ;x0
935: sar ebx,FLOG2 ;y0
936:
937: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
938: jl short oct_1_map_in_bank
939:
940: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
941: jl short oct_1_done_bank_map
942:
943: oct_1_map_in_bank:
944: push eax
945: push ecx
946: push edx
947:
948: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
949:
950: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
951: <esi, ebx, JustifyTop> ;###
952:
953: pop edx
954: pop ecx
955: pop eax
956:
957: public oct_1_done_bank_map
958: oct_1_done_bank_map:
959: mov edi,[esp].sf_lNextScan
960: imul edi,ebx
961: add edi,[esi].pdev_pvBitmapStart
962: add edi,eax ;edi now points to start byte
963:
964: mov ebp,[esi].pdev_rcl1WindowClip.yBottom
965: sub ebp,ebx ;### ebp = # of scans before end of bank
966:
967: mov esi,edx
968: sar esi,FLOG2 ;esi = # of pixels to lay down
969:
970: sub esi,ebp
971: sbb ebx,ebx
972: and ebx,esi
973: add ebp,ebx ;ebp = # of pels in this bank
974:
975: mov [esp].sf_cAfterThisBank,esi
976: mov esi,[esp].sf_lNextScan
977:
978: mov ebx,-1 ;### round x = 1/2 *DOWN* in value
979: sub ebx,edx
980: sar ebx,1 ;now have error term
981:
982: mov eax,[esp].sf_iColor
983:
984: ;-------------------------------------------------------------------------;
985: ; Left-to-right Lines With Abs(Slope) > 1/2
986: ; -----------------------------------------
987: ;
988: ; eax = color
989: ; ebx = error term
990: ; ecx = dM
991: ; edx = dN
992: ; esi = delta
993: ; edi = memory pointer
994: ; ebp = # of scans before end of bank
995: ;-------------------------------------------------------------------------;
996:
997: oct_1_main_loop:
998: dec ebp
999: jl short oct_1_see_if_more
1000: mov [edi],al
1001: add edi,esi
1002: add ebx,ecx ;err += dM
1003: jl short oct_1_main_loop
1004:
1005: inc edi ;one to right
1006: sub ebx,edx ;err -= dN
1007:
1008: ; Unroll a bit:
1009:
1010: dec ebp
1011: jl short oct_1_see_if_more
1012: mov [edi],al
1013: add edi,esi
1014: add ebx,ecx ;err += dM
1015: jl short oct_1_main_loop
1016:
1017: inc edi ;one to right
1018: sub ebx,edx ;err -= dN
1019: jmp short oct_1_main_loop
1020:
1021: public oct_1_see_if_more
1022: oct_1_see_if_more:
1023: mov eax,[esp].sf_cAfterThisBank
1024: cmp eax,0
1025: jle next_line
1026:
1027: mov [esp].sf_pfnReturn,offset oct_1_main_loop
1028: jmp [esp].sf_pfnNextBank
1029:
1030: public oct_1_non_integer
1031: oct_1_non_integer:
1032: GIQR ROUND_X_AND_Y_DOWN ;### round x=1/2, y=1/2 down in value
1033:
1034: mov esi,[esp].sf_ppdev
1035: cmp edi,[esi].pdev_rcl1WindowClip.yTop
1036: jl short oct_1_nonint_map_in_bank
1037:
1038: cmp edi,[esi].pdev_rcl1WindowClip.yBottom
1039: jl short oct_1_nonint_done_bank_map
1040:
1041: oct_1_nonint_map_in_bank:
1042: push eax
1043: push ecx
1044: push edx
1045:
1046: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1047: <esi, edi, JustifyTop> ;###
1048:
1049: pop edx
1050: pop ecx
1051: pop eax
1052:
1053: oct_1_nonint_done_bank_map:
1054: mov [esp].sf_y0,edi
1055: imul edi,[esp].sf_lNextScan
1056: add edi,[esi].pdev_pvBitmapStart
1057: add edi,eax ;edi points to start byte
1058:
1059: mov ebp,[esi].pdev_rcl1WindowClip.yBottom
1060: mov esi,[esp].sf_y1
1061: sub esi,ebp
1062:
1063: sbb eax,eax
1064: and eax,esi
1065: add ebp,eax
1066: sub ebp,[esp].sf_y0 ;ebp = min(y1,
1067: ; ppdev->rcl1WindowClip.yBottom) - y0
1068: ; (# of pixels to lay down)
1069:
1070: mov [esp].sf_cAfterThisBank,esi
1071:
1072: mov esi,[esp].sf_lNextScan
1073: mov eax,[esp].sf_iColor
1074:
1075: jmp oct_1_main_loop
1076:
1077: ;/////////////////////////////////////////////////////////////////////
1078: ;// Octant 3
1079: ;/////////////////////////////////////////////////////////////////////
1080:
1081: octants_2_3_4_5:
1082: neg ecx ;dM = -dM (now positive)
1083: neg eax ;M0 = -M0
1084: sub edx,ebx
1085: jl octants_4_5
1086: cmp ecx,edx
1087: jl octant_2
1088:
1089: public octant_3
1090: octant_3:
1091: mov esi,[esp].sf_lNextScan
1092: mov [esp].sf_lDelta,esi ;we're going down
1093: mov [esp].sf_pfnNextBank,offset bank_x_major_next_lower
1094:
1095: mov esi,eax
1096: or esi,ebx
1097: or esi,ecx
1098: or esi,edx
1099: and esi,F - 1
1100: jnz oct_3_non_integer
1101:
1102: or edx,edx
1103: jz flip_and_do_horizontal_line
1104:
1105: mov esi,[esp].sf_ppdev
1106:
1107: neg eax ;### untransform M0
1108:
1109: sar eax,FLOG2 ;x0
1110: sar ebx,FLOG2 ;y0
1111:
1112: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
1113: jl short oct_3_map_in_bank
1114:
1115: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
1116: jl short oct_3_done_bank_map
1117:
1118: oct_3_map_in_bank:
1119: push eax
1120: push ecx
1121: push edx
1122:
1123: ; ebx, esi, edi and esi are preserved according to C calling conventions:
1124:
1125: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1126: <esi, ebx, JustifyTop> ;###
1127:
1128: pop edx
1129: pop ecx
1130: pop eax
1131:
1132: public oct_3_done_bank_map
1133: oct_3_done_bank_map:
1134: mov edi,[esp].sf_lNextScan
1135: imul edi,ebx
1136: add edi,[esi].pdev_pvBitmapStart
1137: add edi,eax ;edi now points to start byte
1138:
1139: mov ebp,[esi].pdev_rcl1WindowClip.yBottom
1140: sub ebp,ebx ;### ebp = # of scans before end of bank
1141:
1142: mov esi,ecx
1143: sar esi,FLOG2 ;esi = # of pixels to lay down
1144:
1145: mov ebx,-1 ;### round y = 1/2 *DOWN* in value
1146: sub ebx,ecx
1147: sar ebx,1 ;now have error term
1148:
1149: mov eax,[esp].sf_iColor
1150: sub ecx,edx ;ecx = dM - dN
1151: cmp edx,ecx
1152: jg oct_34b
1153:
1154: ;-------------------------------------------------------------------------;
1155: ; Right-to-left Lines With ABS(Slope) <= 1/2
1156: ; ------------------------------------------
1157: ;
1158: ; Since the line's slope is less than 1/2, we have only 3 possibilities
1159: ; at each pair of pixels:
1160: ;
1161: ; Case 1: o Case 2: o o Case 3: o o o
1162: ; o o o
1163: ;
1164: ; Case: err + dN >= 0 err + 2dN >= 0 err + 2dN < 0
1165: ; New: err += 2dN - dM err += 2dN - dM err += 2dN
1166: ;
1167: ; eax = color
1168: ; ebx = error term
1169: ; ecx = dM - dN
1170: ; edx = dN
1171: ; esi = # of pixels to lay down
1172: ; edi = memory pointer
1173: ; ebp = # of scans before end of bank
1174: ;-------------------------------------------------------------------------;
1175:
1176: oct_34a:
1177: test edi,1
1178: jnz short oct_34a_main ;### start is word aligned
1179:
1180: ; Handle unaligned start:
1181:
1182: dec esi
1183: jl next_line
1184:
1185: mov [edi],al
1186: dec edi ;###
1187: add ebx,edx ;err += dN
1188: jl short oct_34a_main
1189:
1190: add edi,[esp].sf_lDelta
1191: dec ebp ;hit a new bank?
1192: jz short oct_34a_next_bank_3
1193: oct_34a_done_bank_3:
1194: sub ebx,ecx ;err += dN - dM
1195: jl short oct_34a_continue
1196:
1197: ;;; Case 1:
1198:
1199: public oct_34a_case_1
1200: oct_34a_case_1:
1201: sub esi,2
1202: jl short oct_34a_done
1203: mov [edi],al
1204: add edi,[esp].sf_lDelta
1205: sub edi,2 ;###
1206: dec ebp
1207: jz short oct_34a_next_bank_1
1208: oct_34a_done_bank_1:
1209: mov [edi+1],al
1210: sub ebx,ecx ;err += dN - dM
1211: ;;;case 1 is done
1212: ;;; Main loop:
1213:
1214: oct_34a_main:
1215: add ebx,edx ;err += dN
1216: jge short oct_34a_case_1
1217: oct_34a_continue:
1218: sub esi,2
1219: jl short oct_34a_done
1220: mov [edi-1],ax ;###
1221: sub edi,2 ;###
1222: add ebx,edx ;err += dN
1223: jl short oct_34a_main ;;;case 3 is done
1224:
1225: ;;; Handle end of case 2:
1226:
1227: add edi,[esp].sf_lDelta
1228: dec ebp
1229: jz short oct_34a_next_bank_2
1230: oct_34a_done_bank_2:
1231: sub ebx,ecx ;err += dN - dM
1232: jge short oct_34a_case_1
1233: jmp short oct_34a_continue ;;;case 2 is done
1234:
1235: oct_34a_done:
1236: inc esi ;esi = -1 means do another pixel
1237: jnz next_line
1238: mov [edi],al
1239: jmp next_line
1240:
1241: oct_34a_next_bank_1:
1242: mov [esp].sf_pfnReturn,offset oct_34a_done_bank_1
1243: jmp [esp].sf_pfnNextBank
1244: oct_34a_next_bank_2:
1245: mov [esp].sf_pfnReturn,offset oct_34a_done_bank_2
1246: jmp [esp].sf_pfnNextBank
1247: oct_34a_next_bank_3:
1248: mov [esp].sf_pfnReturn,offset oct_34a_done_bank_3
1249: jmp [esp].sf_pfnNextBank
1250:
1251: ;-------------------------------------------------------------------------;
1252: ; Right-to-left Lines With 1/2 < ABS(Slope) <= 1
1253: ; ----------------------------------------------
1254: ;
1255: ; Since the line's slope is between 1/2 and 1, we have only 3 possibilities
1256: ; at each pair of pixels:
1257: ;
1258: ; Case 1: o o Case 2: o Case 3: o
1259: ; o o o o
1260: ; o
1261: ;
1262: ; Case: err + dN < 0 err + 2dN - dM < 0 err + 2dN - dM >= 0
1263: ; New: err += 2dN - dM err += 2dN - dM err += 2dN - 2dM
1264: ;
1265: ; eax = color
1266: ; ebx = error term
1267: ; ecx = dM - dN
1268: ; edx = dN
1269: ; esi = # of pixels to lay down
1270: ; edi = memory pointer
1271: ; ebp = # of scans before end of bank
1272: ;-------------------------------------------------------------------------;
1273:
1274: public oct_34b
1275: oct_34b:
1276: test edi,1
1277: jnz short oct_34b_main ;###
1278:
1279: dec esi
1280: jl next_line
1281:
1282: mov [edi],al
1283: dec edi ;###
1284: add ebx,edx ;err += dN
1285: jl short oct_34b_main
1286:
1287: add edi,[esp].sf_lDelta
1288: dec ebp
1289: jz short oct_34b_next_bank_4
1290: oct_34b_done_bank_4:
1291: sub ebx,ecx ;err += dN - dM
1292: jge short oct_34b_continue
1293:
1294: public oct_34b_case_1
1295: oct_34b_case_1:
1296: sub esi,2
1297: jl short oct_34b_done
1298: mov [edi-1],ax ;###
1299: add edi,[esp].sf_lDelta
1300: sub edi,2 ;###
1301: dec ebp
1302: jz short oct_34b_next_bank_1
1303: oct_34b_done_bank_1:
1304: sub ebx,ecx ;err += dN - dM
1305: ;;;case 1 is done
1306: ;;; Main loop:
1307:
1308: oct_34b_main:
1309: add ebx,edx ;err += dN
1310: jl short oct_34b_case_1
1311: oct_34b_continue:
1312: sub esi,2
1313: jl short oct_34b_done
1314: mov [edi],al
1315: add edi,[esp].sf_lDelta
1316: sub edi,2 ;###
1317: dec ebp
1318: jz short oct_34b_next_bank_2
1319: oct_34b_done_bank_2:
1320: mov [edi+1],al
1321: sub ebx,ecx ;err += dN - dM
1322: jl short oct_34b_main ;;;case 2 is done
1323:
1324: add edi,[esp].sf_lDelta
1325: dec ebp
1326: jz oct_34b_next_bank_3
1327: oct_34b_done_bank_3:
1328: sub ebx,ecx ;err += dN - dM
1329: jl short oct_34b_case_1 ;;;case 3 is done
1330: jmp short oct_34b_continue
1331:
1332: oct_34b_next_bank_4:
1333: mov [esp].sf_pfnReturn,offset oct_34b_done_bank_4
1334: jmp [esp].sf_pfnNextBank
1335: oct_34b_next_bank_3:
1336: mov [esp].sf_pfnReturn,offset oct_34b_done_bank_3
1337: jmp [esp].sf_pfnNextBank
1338: oct_34b_next_bank_2:
1339: mov [esp].sf_pfnReturn,offset oct_34b_done_bank_2
1340: jmp [esp].sf_pfnNextBank
1341: oct_34b_next_bank_1:
1342: mov [esp].sf_pfnReturn,offset oct_34b_done_bank_1
1343: jmp [esp].sf_pfnNextBank
1344:
1345: oct_34b_done:
1346: inc esi
1347: jnz next_line ;esi = -1 means do another pixel
1348: mov [edi],al
1349: jmp next_line
1350:
1351: ;-------------------------------------------------------------------------;
1352:
1353: public oct_3_non_integer
1354: oct_3_non_integer:
1355: GIQ ROUND_Y_DOWN ;### round y=1/2 down in value
1356: ;### (remember that we're flipped
1357: ;### in 'x')
1358:
1359: or edx,edx
1360: jz flip_and_do_non_integer_horizontal_line
1361:
1362: mov esi,[esp].sf_ppdev
1363: neg eax ;### Untransform x0
1364: cmp edi,[esi].pdev_rcl1WindowClip.yTop
1365: jl short oct_3_nonint_map_in_bank
1366:
1367: cmp edi,[esi].pdev_rcl1WindowClip.yBottom
1368: jl short oct_3_nonint_done_bank_map
1369:
1370: oct_3_nonint_map_in_bank:
1371: push eax
1372: push ecx
1373: push edx
1374:
1375: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1376: <esi, edi, JustifyTop> ;###
1377:
1378: pop edx
1379: pop ecx
1380: pop eax
1381:
1382: oct_3_nonint_done_bank_map:
1383: mov ebp,[esi].pdev_rcl1WindowClip.yBottom
1384: sub ebp,edi ;### ebp = # scans before end of bank
1385:
1386: imul edi,[esp].sf_lNextScan ;
1387: add edi,[esi].pdev_pvBitmapStart
1388: add edi,eax ;edi now points to start byte
1389:
1390: mov esi,[esp].sf_x1
1391: add esi,eax ;### esi = # pixels to lay down
1392:
1393: mov eax,[esp].sf_iColor
1394:
1395: sub ecx,edx ;ecx = dM - dN
1396: cmp edx,ecx
1397: jg oct_34b
1398: jmp oct_34a
1399:
1400: ;/////////////////////////////////////////////////////////////////////
1401: ;// Octant 2
1402: ;/////////////////////////////////////////////////////////////////////
1403:
1404: public octant_2
1405: octant_2:
1406: mov [esp].sf_pfnNextBank,offset bank_y_major_next_lower
1407:
1408: mov esi,eax
1409: or esi,ebx
1410: or esi,ecx
1411: or esi,edx
1412: and esi,F - 1
1413: jnz oct_2_non_integer
1414:
1415: neg eax ;### untransform M0
1416:
1417: mov esi,[esp].sf_ppdev
1418: sar eax,FLOG2 ;x0
1419: sar ebx,FLOG2 ;y0
1420:
1421: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
1422: jl short oct_2_map_in_bank
1423:
1424: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
1425: jl short oct_2_done_bank_map
1426:
1427: oct_2_map_in_bank:
1428: push eax
1429: push ecx
1430: push edx
1431:
1432: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
1433:
1434: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1435: <esi, ebx, JustifyTop> ;###
1436:
1437: pop edx
1438: pop ecx
1439: pop eax
1440:
1441: public oct_2_done_bank_map
1442: oct_2_done_bank_map:
1443: mov edi,[esp].sf_lNextScan
1444: imul edi,ebx
1445: add edi,[esi].pdev_pvBitmapStart
1446: add edi,eax ;edi now points to start byte
1447:
1448: mov ebp,[esi].pdev_rcl1WindowClip.yBottom
1449: sub ebp,ebx ;### ebp = # of scans before end of bank
1450:
1451: mov esi,edx
1452: sar esi,FLOG2 ;esi = # of pixels to lay down
1453:
1454: sub esi,ebp
1455: sbb ebx,ebx
1456: and ebx,esi
1457: add ebp,ebx ;ebp = # of pels in this bank
1458:
1459: mov [esp].sf_cAfterThisBank,esi
1460: mov esi,[esp].sf_lNextScan
1461:
1462: xor ebx,ebx ;### round x = 1/2 *UP* in value
1463: sub ebx,edx
1464: sar ebx,1 ;now have error term
1465:
1466: mov eax,[esp].sf_iColor
1467:
1468: ;-------------------------------------------------------------------------;
1469: ; Right-to-left Lines With Abs(Slope) > 1/2
1470: ; -----------------------------------------
1471: ;
1472: ; eax = color
1473: ; ebx = error term
1474: ; ecx = dM
1475: ; edx = dN
1476: ; esi = delta
1477: ; edi = memory pointer
1478: ; ebp = # of scans before end of bank
1479: ;-------------------------------------------------------------------------;
1480:
1481: oct_2_main_loop:
1482: dec ebp
1483: jl short oct_2_see_if_more
1484: mov [edi],al
1485: add edi,esi
1486: add ebx,ecx ;err += dM
1487: jl short oct_2_main_loop
1488:
1489: dec edi ;one to left
1490: sub ebx,edx ;err -= dN
1491:
1492: ; Unroll a bit:
1493:
1494: dec ebp
1495: jl short oct_2_see_if_more
1496: mov [edi],al
1497: add edi,esi
1498: add ebx,ecx ;err += dM
1499: jl short oct_2_main_loop
1500:
1501: dec edi ;one to left
1502: sub ebx,edx ;err -= dN
1503: jmp short oct_2_main_loop
1504:
1505: public oct_2_see_if_more
1506: oct_2_see_if_more:
1507: mov eax,[esp].sf_cAfterThisBank
1508: cmp eax,0
1509: jle next_line
1510:
1511: mov [esp].sf_pfnReturn,offset oct_2_main_loop
1512: jmp [esp].sf_pfnNextBank
1513:
1514: public oct_2_non_integer
1515: oct_2_non_integer:
1516: GIQR ROUND_Y_DOWN ;### round y=1/2 down in value
1517: ;### (remember that we're flipped
1518: ;### in 'x')
1519:
1520: mov esi,[esp].sf_ppdev
1521:
1522: neg eax ;### untransform x0
1523:
1524: cmp edi,[esi].pdev_rcl1WindowClip.yTop
1525: jl short oct_2_nonint_map_in_bank
1526:
1527: cmp edi,[esi].pdev_rcl1WindowClip.yBottom
1528: jl short oct_2_nonint_done_bank_map
1529:
1530: oct_2_nonint_map_in_bank:
1531: push eax
1532: push ecx
1533: push edx
1534:
1535: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1536: <esi, edi, JustifyTop> ;###
1537:
1538: pop edx
1539: pop ecx
1540: pop eax
1541:
1542: oct_2_nonint_done_bank_map:
1543: mov [esp].sf_y0,edi
1544: imul edi,[esp].sf_lNextScan
1545: add edi,[esi].pdev_pvBitmapStart
1546: add edi,eax ;edi points to start byte
1547:
1548: mov ebp,[esi].pdev_rcl1WindowClip.yBottom
1549: mov esi,[esp].sf_y1
1550: sub esi,ebp
1551:
1552: sbb eax,eax
1553: and eax,esi
1554: add ebp,eax
1555: sub ebp,[esp].sf_y0 ;ebp = min(y1,
1556: ; ppdev->rcl1WindowClip.yBottom) - y0
1557: ; (# of pixels to lay down)
1558:
1559: mov [esp].sf_cAfterThisBank,esi
1560:
1561: mov esi,[esp].sf_lNextScan
1562: mov eax,[esp].sf_iColor
1563:
1564: jmp oct_2_main_loop
1565:
1566: ;/////////////////////////////////////////////////////////////////////
1567: ;// Octant 4
1568: ;/////////////////////////////////////////////////////////////////////
1569:
1570: octants_4_5:
1571: neg edx
1572: neg ebx
1573: cmp ecx,edx
1574: jl octant_5
1575:
1576: public octant_4
1577: octant_4:
1578: mov esi,[esp].sf_lNextScan
1579: neg esi
1580: mov [esp].sf_lDelta,esi ;we're going up
1581: mov [esp].sf_pfnNextBank,offset bank_x_major_next_upper
1582:
1583: mov esi,eax
1584: or esi,ebx
1585: or esi,ecx
1586: or esi,edx
1587: and esi,F - 1
1588: jnz oct_4_non_integer
1589:
1590: neg eax ;### untransform x
1591: neg ebx ;### untransform y
1592:
1593: mov esi,[esp].sf_ppdev
1594: sar eax,FLOG2 ;x0
1595: sar ebx,FLOG2 ;y0
1596:
1597: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
1598: jl short oct_4_map_in_bank
1599:
1600: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
1601: jl short oct_4_done_bank_map
1602:
1603: oct_4_map_in_bank:
1604: push eax
1605: push ecx
1606: push edx
1607:
1608: ; ebx, esi, edi and esi are preserved according to C calling conventions:
1609:
1610: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1611: <esi, ebx, JustifyBottom> ;###
1612:
1613: pop edx
1614: pop ecx
1615: pop eax
1616:
1617: public oct_4_done_bank_map
1618: oct_4_done_bank_map:
1619: mov edi,[esp].sf_lNextScan
1620: imul edi,ebx
1621: add edi,[esi].pdev_pvBitmapStart
1622: add edi,eax ;edi now points to start byte
1623:
1624: mov ebp,ebx ;###
1625: sub ebp,[esi].pdev_rcl1WindowClip.yTop
1626: inc ebp ;### ebp = # scans before end of bank
1627:
1628: mov esi,ecx
1629: sar esi,FLOG2 ;esi = # of pixels to lay down
1630:
1631: xor ebx,ebx ;### round y = 1/2 *UP* in value
1632: sub ebx,ecx
1633: sar ebx,1 ;now have error term
1634:
1635: mov eax,[esp].sf_iColor
1636: sub ecx,edx ;ecx = dM - dN
1637: cmp edx,ecx
1638: jg oct_34b
1639: jmp oct_34a
1640:
1641: public oct_4_non_integer
1642: oct_4_non_integer:
1643: cmp ecx,edx
1644: je oct_4_slope_one
1645: GIQ 0 ;###
1646: ;### (remember that we're flipped
1647: ;### in 'x' and 'y')
1648:
1649: oct_4_common:
1650: mov esi,[esp].sf_ppdev
1651: neg edi ;### untransform y
1652: neg eax ;### untransform x
1653:
1654: cmp edi,[esi].pdev_rcl1WindowClip.yTop
1655: jl short oct_4_nonint_map_in_bank
1656:
1657: cmp edi,[esi].pdev_rcl1WindowClip.yBottom
1658: jl short oct_4_nonint_done_bank_map
1659:
1660: oct_4_nonint_map_in_bank:
1661: push eax
1662: push ecx
1663: push edx
1664:
1665: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1666: <esi, edi, JustifyBottom>;###
1667:
1668: pop edx
1669: pop ecx
1670: pop eax
1671:
1672: oct_4_nonint_done_bank_map:
1673: mov ebp,edi ;###
1674: sub ebp,[esi].pdev_rcl1WindowClip.yTop
1675: inc ebp ;### esp = # scans before end of bank
1676:
1677: imul edi,[esp].sf_lNextScan
1678: add edi,[esi].pdev_pvBitmapStart
1679: add edi,eax ;edi now points to start byte
1680:
1681: mov esi,[esp].sf_x1
1682: add esi,eax ;### esi = # pixels to lay down
1683:
1684: mov eax,[esp].sf_iColor
1685:
1686: sub ecx,edx ;ecx = dM - dN
1687: cmp edx,ecx
1688: jg oct_34b
1689: jmp oct_34a
1690:
1691: ;-------------------------------------------------------------------;
1692: ; 45 degree lines have a special rounding rule: when the line
1693: ; runs exactly half way between to pixels, the upper or right pel
1694: ; is illuminated. This translates into x=1/2 rounding up, and
1695: ; y=1/2 rounding down in value:
1696:
1697: public oct_4_slope_one
1698: oct_4_slope_one:
1699: GIQ ROUND_X_DOWN_SLOPE_ONE ;round x=1/2 down in value
1700: jmp oct_4_common
1701:
1702: ;/////////////////////////////////////////////////////////////////////
1703: ;// Octant 5
1704: ;/////////////////////////////////////////////////////////////////////
1705:
1706: public octant_5
1707: octant_5:
1708: mov [esp].sf_pfnNextBank,offset bank_y_major_next_upper
1709:
1710: mov esi,eax
1711: or esi,ebx
1712: or esi,ecx
1713: or esi,edx
1714: and esi,F - 1
1715: jnz oct_5_non_integer
1716:
1717: mov esi,[esp].sf_ppdev
1718: neg eax ;### untransform
1719: neg ebx ;### untransform
1720: sar eax,FLOG2 ;x0
1721: sar ebx,FLOG2 ;y0
1722:
1723: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
1724: jl short oct_5_map_in_bank
1725:
1726: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
1727: jl short oct_5_done_bank_map
1728:
1729: oct_5_map_in_bank:
1730: push eax
1731: push ecx
1732: push edx
1733:
1734: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
1735:
1736: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1737: <esi,ebx,JustifyBottom> ;###
1738:
1739: pop edx
1740: pop ecx
1741: pop eax
1742:
1743: public oct_5_done_bank_map
1744: oct_5_done_bank_map:
1745: mov edi,[esp].sf_lNextScan
1746: imul edi,ebx
1747: add edi,[esi].pdev_pvBitmapStart
1748: add edi,eax ;edi now points to start byte
1749:
1750: mov ebp,ebx ;###
1751: sub ebp,[esi].pdev_rcl1WindowClip.yTop
1752: inc ebp ;### ebp = # scans before end of bank
1753:
1754: mov esi,edx
1755: sar esi,FLOG2 ;esi = # of pixels to lay down
1756:
1757: sub esi,ebp
1758: sbb ebx,ebx
1759: and ebx,esi
1760: add ebp,ebx ;ebp = # of pels in this bank
1761:
1762: mov [esp].sf_cAfterThisBank,esi
1763: mov esi,[esp].sf_lNextScan
1764: neg esi ;### going down!
1765:
1766: xor ebx,ebx ;### round x = 1/2 *UP* in value
1767: sub ebx,edx
1768: sar ebx,1 ;now have error term
1769:
1770: mov eax,[esp].sf_iColor
1771: jmp oct_2_main_loop
1772:
1773: public oct_5_non_integer
1774: oct_5_non_integer:
1775: GIQR 0 ;###
1776: ;### (remember that we're flipped
1777: ;### in 'x' and 'y')
1778:
1779: mov esi,[esp].sf_ppdev
1780:
1781: neg edi ;### untransform y0
1782: neg eax ;### untransform x0
1783:
1784: cmp edi,[esi].pdev_rcl1WindowClip.yTop
1785: jl short oct_5_nonint_map_in_bank
1786:
1787: cmp edi,[esi].pdev_rcl1WindowClip.yBottom
1788: jl short oct_5_nonint_done_bank_map
1789:
1790: oct_5_nonint_map_in_bank:
1791: push eax
1792: push ecx
1793: push edx
1794:
1795: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1796: <esi,edi,JustifyBottom> ;###
1797:
1798: pop edx
1799: pop ecx
1800: pop eax
1801:
1802: oct_5_nonint_done_bank_map:
1803: mov [esp].sf_y0,edi
1804: imul edi,[esp].sf_lNextScan
1805: add edi,[esi].pdev_pvBitmapStart
1806: add edi,eax ;edi points to start byte
1807:
1808: mov ebp,[esp].sf_y0 ;###
1809: mov esi,[esi].pdev_rcl1WindowClip.yTop
1810: dec esi ;### make top exclusive
1811: sub ebp,esi ;###
1812: add esi,[esp].sf_y1 ;### don't forget that y1 wasn't un-
1813: ;### transformed (so this is an 'add')
1814:
1815: jg short @F ;###
1816: add ebp,esi ;###
1817: @@:
1818: mov [esp].sf_cAfterThisBank,esi
1819:
1820: mov esi,[esp].sf_lNextScan
1821: neg esi ;### going down!
1822: mov eax,[esp].sf_iColor
1823:
1824: jmp oct_2_main_loop
1825:
1826: ;/////////////////////////////////////////////////////////////////////
1827: ;// Octant 6
1828: ;/////////////////////////////////////////////////////////////////////
1829:
1830: public octants_6_7
1831: octants_6_7:
1832: neg edx ;dN = -dN (now positive)
1833: neg ebx ;M1 = -M1
1834: cmp ecx,edx
1835: jge octant_7
1836:
1837: public octant_6
1838: octant_6:
1839: mov [esp].sf_pfnNextBank,offset bank_y_major_next_upper
1840:
1841: mov esi,eax
1842: or esi,ebx
1843: or esi,ecx
1844: or esi,edx
1845: and esi,F - 1
1846: jnz oct_6_non_integer
1847:
1848: mov esi,[esp].sf_ppdev
1849: neg ebx ;### untransform
1850: sar eax,FLOG2 ;x0
1851: sar ebx,FLOG2 ;y0
1852:
1853: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
1854: jl short oct_6_map_in_bank
1855:
1856: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
1857: jl short oct_6_done_bank_map
1858:
1859: oct_6_map_in_bank:
1860: push eax
1861: push ecx
1862: push edx
1863:
1864: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
1865:
1866: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1867: <esi,ebx,JustifyBottom> ;###
1868:
1869: pop edx
1870: pop ecx
1871: pop eax
1872:
1873: public oct_6_done_bank_map
1874: oct_6_done_bank_map:
1875: mov edi,[esp].sf_lNextScan
1876: imul edi,ebx
1877: add edi,[esi].pdev_pvBitmapStart
1878: add edi,eax ;edi now points to start byte
1879:
1880: mov ebp,ebx ;###
1881: sub ebp,[esi].pdev_rcl1WindowClip.yTop
1882: inc ebp ;### ebp = # scans before end of bank
1883:
1884: mov esi,edx
1885: sar esi,FLOG2 ;esi = # of pixels to lay down
1886:
1887: sub esi,ebp
1888: sbb ebx,ebx
1889: and ebx,esi
1890: add ebp,ebx ;ebp = # of pels in this bank
1891:
1892: mov [esp].sf_cAfterThisBank,esi
1893: mov esi,[esp].sf_lNextScan
1894: neg esi ;### going down!
1895:
1896: mov ebx,-1 ;### round x = 1/2 *DOWN* in value
1897: sub ebx,edx
1898: sar ebx,1 ;now have error term
1899:
1900: mov eax,[esp].sf_iColor
1901: jmp oct_1_main_loop
1902:
1903: public oct_6_non_integer
1904: oct_6_non_integer:
1905: GIQR ROUND_X_DOWN ;### round x=1/2 down in value
1906: ;### (remember that we're flipped
1907: ;### in 'y')
1908:
1909: mov esi,[esp].sf_ppdev
1910:
1911: neg edi ;### untransform y0
1912:
1913: cmp edi,[esi].pdev_rcl1WindowClip.yTop
1914: jl short oct_6_nonint_map_in_bank
1915:
1916: cmp edi,[esi].pdev_rcl1WindowClip.yBottom
1917: jl short oct_6_nonint_done_bank_map
1918:
1919: oct_6_nonint_map_in_bank:
1920: push eax
1921: push ecx
1922: push edx
1923:
1924: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1925: <esi,edi,JustifyBottom> ;###
1926:
1927: pop edx
1928: pop ecx
1929: pop eax
1930:
1931: oct_6_nonint_done_bank_map:
1932: mov [esp].sf_y0,edi
1933: imul edi,[esp].sf_lNextScan
1934: add edi,[esi].pdev_pvBitmapStart
1935: add edi,eax ;edi points to start byte
1936:
1937: mov ebp,[esp].sf_y0 ;###
1938: mov esi,[esi].pdev_rcl1WindowClip.yTop
1939: dec esi ;### make top exclusive
1940: sub ebp,esi ;###
1941: add esi,[esp].sf_y1 ;### don't forget that y1 wasn't un-
1942: ;### transformed (so this is an 'add')
1943:
1944: jg short @F ;###
1945: add ebp,esi ;###
1946: @@:
1947: mov [esp].sf_cAfterThisBank,esi
1948:
1949: mov esi,[esp].sf_lNextScan
1950: neg esi ;### going down!
1951: mov eax,[esp].sf_iColor
1952:
1953: jmp oct_1_main_loop
1954:
1955: ;/////////////////////////////////////////////////////////////////////
1956: ;// Octant 7
1957: ;/////////////////////////////////////////////////////////////////////
1958:
1959: public octant_7
1960: octant_7:
1961: mov esi,[esp].sf_lNextScan
1962: neg esi
1963: mov [esp].sf_lDelta,esi ;we're going up
1964: mov [esp].sf_pfnNextBank,offset bank_x_major_next_upper
1965:
1966: mov esi,eax
1967: or esi,ebx
1968: or esi,ecx
1969: or esi,edx
1970: and esi,F - 1
1971: jnz oct_7_non_integer
1972:
1973: neg ebx ;### untransform y
1974:
1975: mov esi,[esp].sf_ppdev
1976: sar eax,FLOG2 ;x0
1977: sar ebx,FLOG2 ;y0
1978:
1979: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
1980: jl short oct_7_map_in_bank
1981:
1982: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
1983: jl short oct_7_done_bank_map
1984:
1985: oct_7_map_in_bank:
1986: push eax
1987: push ecx
1988: push edx
1989:
1990: ; ebx, esi, edi and esi are preserved according to C calling conventions:
1991:
1992: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
1993: <esi, ebx, JustifyBottom> ;###
1994:
1995: pop edx
1996: pop ecx
1997: pop eax
1998:
1999: public oct_7_done_bank_map
2000: oct_7_done_bank_map:
2001: mov edi,[esp].sf_lNextScan
2002: imul edi,ebx
2003: add edi,[esi].pdev_pvBitmapStart
2004: add edi,eax ;edi now points to start byte
2005:
2006: mov ebp,ebx ;###
2007: sub ebp,[esi].pdev_rcl1WindowClip.yTop
2008: inc ebp ;### ebp = # scans before end of bank
2009:
2010: mov esi,ecx
2011: sar esi,FLOG2 ;esi = # of pixels to lay down
2012:
2013: xor ebx,ebx ;### round y = 1/2 *UP* in value
2014: sub ebx,ecx
2015: sar ebx,1 ;now have error term
2016:
2017: mov eax,[esp].sf_iColor
2018: sub ecx,edx ;ecx = dM - dN
2019: cmp edx,ecx
2020: jg oct_07b
2021: jmp oct_07a
2022:
2023: public oct_7_non_integer
2024: oct_7_non_integer:
2025: cmp ecx,edx
2026: je oct_7_slope_one
2027: GIQ ROUND_X_DOWN ;### round x=1/2 down in value
2028: ;### (remember that we're flipped
2029: ;### in 'y')
2030:
2031: oct_7_common:
2032: mov esi,[esp].sf_ppdev
2033: neg edi ;### untransform y
2034:
2035: cmp edi,[esi].pdev_rcl1WindowClip.yTop
2036: jl short oct_7_nonint_map_in_bank
2037:
2038: cmp edi,[esi].pdev_rcl1WindowClip.yBottom
2039: jl short oct_7_nonint_done_bank_map
2040:
2041: oct_7_nonint_map_in_bank:
2042: push eax
2043: push ecx
2044: push edx
2045:
2046: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
2047: <esi, edi, JustifyBottom>;###
2048:
2049: pop edx
2050: pop ecx
2051: pop eax
2052:
2053: oct_7_nonint_done_bank_map:
2054: mov ebp,edi ;###
2055: sub ebp,[esi].pdev_rcl1WindowClip.yTop
2056: inc ebp ;### esp = # scans before end of bank
2057:
2058: imul edi,[esp].sf_lNextScan
2059: add edi,[esi].pdev_pvBitmapStart
2060: add edi,eax ;edi now points to start byte
2061:
2062: mov esi,[esp].sf_x1
2063: sub esi,eax ;esi = # pixels to lay down
2064:
2065: mov eax,[esp].sf_iColor
2066:
2067: sub ecx,edx ;ecx = dM - dN
2068: cmp edx,ecx
2069: jg oct_07b
2070: jmp oct_07a
2071:
2072: ;-------------------------------------------------------------------;
2073: ; We have to special case those lines with a slope of exactly -1 when
2074: ; 'x' rounds down in value after normalizing:
2075:
2076: public oct_7_slope_one
2077: oct_7_slope_one:
2078: GIQ ROUND_X_DOWN_SLOPE_ONE
2079: jmp oct_7_common
2080:
2081: ;-------------------------------------------------------------------------;
2082: ; Function to get next lower bank for x-major lines.
2083: ;-------------------------------------------------------------------------;
2084:
2085: public bank_x_major_next_lower
2086: bank_x_major_next_lower:
2087: push ebx
2088: mov ebx,[esp+4].sf_ppdev ;NOTE: Add 4 because of above push!
2089: push ecx
2090: push edx
2091: push esi
2092:
2093: mov esi,[ebx].pdev_rcl1WindowClip.yBottom
2094: sub edi,[ebx].pdev_pvBitmapStart
2095:
2096: ptrCall <dword ptr [ebx].pdev_pfnBankControl>, \
2097: <ebx,esi,JustifyTop>
2098:
2099: add edi,[ebx].pdev_pvBitmapStart
2100: mov ebp,[ebx].pdev_rcl1WindowClip.yBottom
2101: sub ebp,esi
2102:
2103: pop esi
2104: pop edx
2105: pop ecx
2106: pop ebx
2107: mov eax,[esp].sf_iColor
2108:
2109: jmp [esp].sf_pfnReturn
2110:
2111: ;-------------------------------------------------------------------------;
2112: ; Function to get next upper bank for x-major lines.
2113: ;-------------------------------------------------------------------------;
2114:
2115: public bank_x_major_next_upper
2116: bank_x_major_next_upper:
2117: push ebx
2118: mov ebx,[esp+4].sf_ppdev ;NOTE: Add 4 because of above push!
2119: push ecx
2120: push edx
2121: push esi
2122:
2123: mov esi,[ebx].pdev_rcl1WindowClip.yTop
2124: dec esi
2125: sub edi,[ebx].pdev_pvBitmapStart
2126:
2127: ptrCall <dword ptr [ebx].pdev_pfnBankControl>, \
2128: <ebx,esi,JustifyBottom>
2129:
2130: add edi,[ebx].pdev_pvBitmapStart
2131: lea ebp,[esi+1]
2132: sub ebp,[ebx].pdev_rcl1WindowClip.yTop
2133:
2134: pop esi
2135: pop edx
2136: pop ecx
2137: pop ebx
2138: mov eax,[esp].sf_iColor
2139:
2140: jmp [esp].sf_pfnReturn
2141:
2142: ;-------------------------------------------------------------------------;
2143: ; Function to get next lower bank for y-major lines.
2144: ;-------------------------------------------------------------------------;
2145:
2146: public bank_y_major_next_lower
2147: bank_y_major_next_lower:
2148:
2149: ; eax = # pels after this bank
2150:
2151: push ebx
2152: mov ebx,[esp+4].sf_ppdev ;NOTE: Plus 4 because of above push!
2153: push ecx
2154: push edx
2155: push esi
2156:
2157: mov esi,[ebx].pdev_rcl1WindowClip.yBottom
2158: sub edi,[ebx].pdev_pvBitmapStart
2159:
2160: push eax
2161: ptrCall <dword ptr [ebx].pdev_pfnBankControl>, \
2162: <ebx,esi,JustifyTop>
2163: pop eax
2164:
2165: add edi,[ebx].pdev_pvBitmapStart
2166: mov ebp,[ebx].pdev_rcl1WindowClip.yBottom
2167: sub ebp,esi ;ebp = # of pels can do in this bank
2168: sub eax,ebp ;esi = # of pels after this bank
2169: sbb ebx,ebx
2170: and ebx,eax
2171: add ebp,ebx ;ebp = # of pels in this bank
2172:
2173: pop esi
2174: pop edx
2175: pop ecx
2176: pop ebx
2177:
2178: mov [esp].sf_cAfterThisBank,eax
2179: ;this has to be done after 'esp' is
2180: ; restored!
2181:
2182: mov eax,[esp].sf_iColor
2183:
2184: jmp [esp].sf_pfnReturn
2185:
2186: ;-------------------------------------------------------------------------;
2187: ; Function to get next upper bank for y-major lines.
2188: ;-------------------------------------------------------------------------;
2189:
2190: public bank_y_major_next_upper
2191: bank_y_major_next_upper:
2192:
2193: ; eax = # pels after this bank
2194:
2195: push ebx
2196: mov ebx,[esp+4].sf_ppdev ;NOTE: Plus 4 because of above push!
2197: push ecx
2198: push edx
2199: push esi
2200:
2201: mov ebp,[ebx].pdev_rcl1WindowClip.yTop
2202: dec ebp
2203:
2204: sub edi,[ebx].pdev_pvBitmapStart
2205:
2206: push eax
2207: ptrCall <dword ptr [ebx].pdev_pfnBankControl>, \
2208: <ebx,ebp,JustifyBottom>
2209: pop eax
2210:
2211: add edi,[ebx].pdev_pvBitmapStart
2212:
2213: inc ebp ;restore exclusiveness
2214: sub ebp,[ebx].pdev_rcl1WindowClip.yTop
2215: ;ebp = # of pels can do in this bank
2216: sub eax,ebp ;esi = # of pels after this bank
2217: sbb ebx,ebx
2218: and ebx,eax
2219: add ebp,ebx ;ebp = # of pels in this bank
2220:
2221: pop esi
2222: pop edx
2223: pop ecx
2224: pop ebx
2225:
2226: mov [esp].sf_cAfterThisBank,eax
2227: ;this has to be done after 'esp' is
2228: ; restored!
2229:
2230: mov eax,[esp].sf_iColor
2231:
2232: jmp [esp].sf_pfnReturn
2233:
2234: ;/////////////////////////////////////////////////////////////////////
2235: ;// Horizontal Line
2236: ;/////////////////////////////////////////////////////////////////////
2237:
2238: public flip_and_do_non_integer_horizontal_line
2239: flip_and_do_non_integer_horizontal_line:
2240: mov ebx,edi
2241: mov ecx,[esp].sf_x1
2242: sub ecx,eax
2243: jle next_line
2244: add eax,ecx
2245: neg eax
2246: inc eax ;x0' = -(-original x0 - dx) + 1
2247: jmp short horizontal_common
2248:
2249: public do_non_integer_horizontal_line
2250: do_non_integer_horizontal_line:
2251: mov ebx,edi
2252: mov ecx,[esp].sf_x1
2253: sub ecx,eax
2254: jg short horizontal_common
2255: jmp next_line
2256:
2257: public flip_and_do_horizontal_line
2258: flip_and_do_horizontal_line:
2259:
2260: ; This 'flip' entry point is for lines that were originally right-to-left:
2261:
2262: add eax,ecx
2263: neg eax
2264: add eax,F ;M0' = -(-original M0 - original dM) + 1
2265:
2266: public do_horizontal_line
2267: do_horizontal_line:
2268: sar eax,FLOG2 ;x0 (we're now in pixel coordinates)
2269: sar ebx,FLOG2 ;y0
2270: sar ecx,FLOG2 ;dx
2271: jz next_line
2272:
2273: ; NOTE: Have to have some pixels to light at this point
2274: ;
2275: ; eax = x0 (in pixel coordinates)
2276: ; ebx = y0
2277: ; ecx = dx (# pixels to light)
2278:
2279: horizontal_common:
2280: mov esi,[esp].sf_ppdev
2281:
2282: cmp ecx,NUM_PELS_NEEDED_FOR_PLANAR_HORIZONTAL
2283: jl do_short_horizontal_line
2284:
2285: test [esi].pdev_fl,DRIVER_PLANAR_CAPABLE
2286: jz do_short_horizontal_line
2287:
2288: ;---------------------------------------------------------------------;
2289: ; Draw horizontal lines using planar mode.
2290: ;
2291: ; NOTE: This code assumes that the length is at least 8 pels long!
2292:
2293: public horizontal_planar
2294: horizontal_planar:
2295: mov edi,[esi].pdev_lPlanarNextScan
2296: imul edi,ebx
2297:
2298: cmp ebx,[esi].pdev_rcl1PlanarClip.yTop
2299: jl short hor_planar_map_bank
2300:
2301: cmp ebx,[esi].pdev_rcl1PlanarClip.yBottom
2302: jl short hor_planar_done_bank
2303:
2304: hor_planar_map_bank:
2305: push eax
2306: push ecx
2307:
2308: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
2309:
2310: ptrCall <dword ptr [esi].pdev_pfnPlanarControl>, \
2311: <esi,ebx,JustifyTop>
2312:
2313: pop ecx
2314: pop eax
2315:
2316: hor_planar_done_bank:
2317: add edi,[esi].pdev_pvBitmapStart
2318:
2319: mov ebp,eax ;save x0
2320: sar eax,2
2321: add edi,eax ;edi now points to start byte
2322:
2323: and ebp,3
2324: jz short hor_planar_start_middle
2325:
2326: ; When the left end doesn't start on a quadpixel boundary, we have to
2327: ; adjust the start address and do some other stuff:
2328:
2329: mov [esp].sf_pjStart,edi
2330: inc edi
2331: sub ebp,4
2332: add ecx,ebp ;adjust byte count to account for
2333: ; fractional start
2334:
2335: hor_planar_start_middle:
2336: mov eax,[esp].sf_iColor ;load the color
2337: mov esi,ecx ;save length
2338:
2339: test edi,1
2340: jz short hor_planar_middle_aligned
2341: mov [edi],al ;handle unaligned whole start byte
2342: inc edi
2343: sub ecx,4
2344: hor_planar_middle_aligned:
2345: shr ecx,3 ;NOTE: we look at the carry later!
2346: rep stosw ;write middle as words
2347: jnc short hor_planar_handle_ends
2348: ;NOTE: here we look at the carry!
2349: mov [edi],al ;handle whole end byte
2350: inc edi
2351:
2352: hor_planar_handle_ends:
2353: mov edx,VGA_BASE + SEQ_DATA
2354: and esi,3
2355: jz short hor_planar_left
2356: hor_planar_right:
2357: mov ecx,esi
2358: mov eax,0f0h
2359: rol al,cl ;we compute the mask instead of
2360: ; using a look-up table, because the
2361: ; table probably wouldn't be in the
2362: ; cache
2363:
2364: ; Set right mask by disabling some planes:
2365:
2366: out dx,al
2367:
2368: push eax ;we add a delay here because some
2369: pop eax ; cards can't handle a write too soon
2370: ; after an out. Hopefully this will
2371: ; help.
2372:
2373: mov eax,[esp].sf_iColor
2374: mov [edi],al
2375:
2376: hor_planar_left:
2377: and ebp,3
2378: jz short hor_planar_done
2379:
2380: mov ecx,ebp
2381: mov eax,0fh
2382: shl eax,cl
2383:
2384: ; Set left mask by disabling some planes:
2385:
2386: out dx,al
2387:
2388: push eax ;we add a delay here because some
2389: pop eax ; cards can't handle a write too soon
2390: ; after an out. Hopefully this will
2391: ; help.
2392:
2393: mov edi,[esp].sf_pjStart
2394: mov eax,[esp].sf_iColor
2395: mov [edi],al
2396:
2397: hor_planar_done:
2398: mov al,MM_ALL
2399: out dx,al
2400:
2401: jmp next_line
2402:
2403: ;---------------------------------------------------------------------;
2404: ; Draw horizontal lines using linear mode.
2405:
2406: public do_short_horizontal_line
2407: do_short_horizontal_line:
2408: mov edi,[esp].sf_lNextScan
2409: imul edi,ebx
2410: add edi,eax
2411:
2412: cmp ebx,[esi].pdev_rcl1WindowClip.yTop
2413: jl short hor_map_in_bank
2414:
2415: cmp ebx,[esi].pdev_rcl1WindowClip.yBottom
2416: jl short hor_done_bank_map
2417:
2418: hor_map_in_bank:
2419: push ecx
2420:
2421: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
2422:
2423: ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
2424: <esi,ebx,JustifyTop>
2425:
2426: pop ecx
2427:
2428: hor_done_bank_map:
2429: add edi,[esi].pdev_pvBitmapStart
2430: ;edi now points to start byte
2431: mov eax,[esp].sf_iColor
2432:
2433: test edi,1
2434: jz short hor_aligned
2435: mov [edi],al ;write initial unaligned byte
2436: inc edi
2437: dec ecx
2438: jz next_line
2439:
2440: hor_aligned:
2441: shr ecx,1 ;NOTE: we look at the carry later!
2442: rep stosw ;write middle words
2443: jnc next_line ;NOTE: here we look at the carry!
2444: mov [edi],al ;write last byte
2445: jmp next_line
2446:
2447:
2448: endProc vFastLine
2449:
2450: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.