Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1235 lines
38 KiB

  1. ;---------------------------Module-Header------------------------------;
  2. ; Module Name: lines.asm
  3. ;
  4. ; ASM version of the line DDA calculator.
  5. ;
  6. ; Copyright (c) 1992-1994 Microsoft Corporation
  7. ;-----------------------------------------------------------------------;
  8. .386
  9. .model small,c
  10. assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
  11. assume fs:nothing,gs:nothing
  12. .xlist
  13. include stdcall.inc ;calling convention cmacros
  14. include i386\strucs.inc
  15. include i386\lines.inc
  16. .list
  17. .data
  18. public gaflRoundTable
  19. gaflRoundTable label dword
  20. dd FL_H_ROUND_DOWN + FL_V_ROUND_DOWN ; no flips
  21. dd FL_H_ROUND_DOWN + FL_V_ROUND_DOWN ; D flip
  22. dd FL_H_ROUND_DOWN ; V flip
  23. dd FL_V_ROUND_DOWN ; D & V flip
  24. dd FL_V_ROUND_DOWN ; slope one
  25. dd 0baadf00dh
  26. dd FL_H_ROUND_DOWN ; slope one & V flip
  27. dd 0baadf00dh
  28. .code
  29. ;--------------------------------Macro----------------------------------;
  30. ; testb ebx, <mask>
  31. ;
  32. ; Substitutes a byte compare if the mask is entirely in the lo-byte or
  33. ; hi-byte (thus saving 3 bytes of code space).
  34. ;
  35. ;-----------------------------------------------------------------------;
  36. TESTB macro targ,mask,thirdarg
  37. local mask2,delta
  38. ifnb <thirdarg>
  39. .err TESTB mask must be enclosed in brackets!
  40. endif
  41. delta = 0
  42. mask2 = mask
  43. if mask2 AND 0ffff0000h
  44. test targ,mask ; If bit set in hi-word,
  45. exitm ; test entire dword
  46. endif
  47. if mask2 AND 0ff00h
  48. if mask2 AND 0ffh ; If bit set in lo-byte and
  49. test targ,mask ; hi-byte, test entire dword
  50. exitm
  51. endif
  52. mask2 = mask2 SHR 8
  53. delta = 1
  54. endif
  55. ifidni <targ>,<EBX>
  56. if delta
  57. test bh,mask2
  58. else
  59. test bl,mask2
  60. endif
  61. exitm
  62. endif
  63. .err Too bad TESTB doesn't support targets other than ebx!
  64. endm
  65. ;---------------------------Public-Routine------------------------------;
  66. ; bLines(ppdev, pptfxFirst, pptfxBuf, prun, cptfx, pls,
  67. ; prclClip, apfn[], flStart)
  68. ;
  69. ; Handles lines with trivial or simple clipping.
  70. ;
  71. ;-----------------------------------------------------------------------;
  72. cProc bLines,36,< \
  73. uses esi edi ebx, \
  74. ppdev: ptr, \
  75. pptfxFirst: ptr, \
  76. pptfxBuf: ptr, \
  77. prun: ptr, \
  78. cptfx: dword, \
  79. pls: ptr, \
  80. prclClip: ptr, \
  81. apfn: ptr, \
  82. flStart: dword >
  83. local pptfxBufEnd: ptr ; Last point in pptfxBuf
  84. local M0: dword ; Normalized x0 in device coords
  85. local dM: dword ; Delta-x in device coords
  86. local N0: dword ; Normalized y0 in device coords
  87. local dN: dword ; Delta-y in device coords
  88. local fl: dword ; Flags for current line
  89. local x: dword ; Normalized start pixel x-coord
  90. local y: dword ; Normalized start pixel y-coord
  91. local eqGamma_lo: dword ; Upper 32 bits of Gamma
  92. local eqGamma_hi: dword ; Lower 32 bits of Gamma
  93. local x0: dword ; Start pixel x-offset
  94. local y0: dword ; Start pixel y-offset
  95. local ulSlopeOneAdjustment: dword ; Special offset if line of slope 1
  96. local cStylePels: dword ; # of pixels in line (before clip)
  97. local xStart: dword ; Start pixel x-offset before clip
  98. local pfn: ptr ; Pointer to strip drawing function
  99. local cPels: dword ; # pixels to be drawn (after clip)
  100. local i: dword ; # pixels in strip
  101. local r: dword ; Remainder (or "error") term
  102. local d_I: dword ; Delta-I
  103. local d_R: dword ; Delta-R
  104. local plStripEnd: ptr ; Last strip in buffer
  105. local ptlStart[size POINTL]: byte ; Unnormalized start coord
  106. local dN_Original: dword ; dN before half-flip
  107. local xClipLeft: dword ; Left side of clip rectangle
  108. local xClipRight: dword ; Right side of clip rectangle
  109. local strip[size STRIPS]: byte ; Our strip buffer
  110. mov ecx, cptfx
  111. mov edx, pptfxBuf
  112. lea eax, [edx + ecx * (size POINTL) - (size POINTL)]
  113. mov pptfxBufEnd, eax ; pptfxBufEnd is inclusive of end point
  114. mov eax, [edx].ptl_x ; Load up end point (M1, N1)
  115. mov edi, [edx].ptl_y
  116. mov edx, pptfxFirst ; Load up start point (M0, N0)
  117. mov esi, [edx].ptl_x
  118. mov ecx, [edx].ptl_y
  119. mov ebx, flStart
  120. ;-----------------------------------------------------------------------;
  121. ; Flip to the first octant. ;
  122. ;-----------------------------------------------------------------------;
  123. ; Register state: esi = M0
  124. ; ecx = N0
  125. ; eax = dM (M1)
  126. ; edi = dN (N1)
  127. ; ebx = fl
  128. ; Make sure we go left to right:
  129. the_main_loop:
  130. cmp esi, eax
  131. jle short is_left_to_right ; skip if M0 <= M1
  132. xchg esi, eax ; swap M0, M1
  133. xchg ecx, edi ; swap N0, N1
  134. or ebx, FL_FLIP_H
  135. is_left_to_right:
  136. ; Compute the deltas, remembering that the DDI says we should get
  137. ; deltas less than 2^31. If we get more, we ensure we don't crash
  138. ; later on by simply skipping the line:
  139. sub eax, esi ; eax = dM
  140. jo next_line ; dM must be less than 2^31
  141. sub edi, ecx ; edi = dN
  142. jo next_line ; dN must be less than 2^31
  143. jge short is_top_to_bottom ; skip if dN >= 0
  144. neg ecx ; N0 = -N0
  145. neg edi ; N1 = -N1
  146. or ebx, FL_FLIP_V
  147. is_top_to_bottom:
  148. cmp edi, eax
  149. jb short done_flips ; skip if dN < dM
  150. jne short slope_more_than_one
  151. ; We must special case slopes of one:
  152. or ebx, FL_FLIP_SLOPE_ONE
  153. jmp short done_flips
  154. slope_more_than_one:
  155. xchg eax, edi ; swap dM, dN
  156. xchg esi, ecx ; swap M0, N0
  157. or ebx, FL_FLIP_D
  158. done_flips:
  159. mov edx, ebx
  160. and edx, FL_ROUND_MASK
  161. .errnz FL_ROUND_SHIFT - 2
  162. or ebx, [gaflRoundTable + edx] ; get our rounding flags
  163. mov dM, eax ; save some info
  164. mov dN, edi
  165. mov fl, ebx
  166. mov edx, esi ; x = LFLOOR(M0)
  167. sar edx, FLOG2
  168. mov x, edx
  169. mov edx, ecx ; y = LFLOOR(N0)
  170. sar edx, FLOG2
  171. mov y, edx
  172. ;-----------------------------------------------------------------------;
  173. ; Compute the fractional remainder term ;
  174. ;-----------------------------------------------------------------------;
  175. public compute_fractional
  176. compute_fractional::
  177. and esi, F - 1 ; M0 = FXFRAC(M0)
  178. and ecx, F - 1 ; N0 = FXFRAC(N0)
  179. mov M0, esi ; save M0, N0 for later
  180. mov N0, ecx
  181. lea edx, [ecx + F/2]
  182. mul edx ; [edx:eax] = dM * (N0 + F/2)
  183. xchg eax, edi
  184. mov ecx, edx ; [ecx:edi] = dM * (N0 + F/2)
  185. ; (we just nuked N0)
  186. mul esi ; [edx:eax] = dN * M0
  187. ; Now gamma = dM * (N0 + F/2) - dN * M0 - bRoundDown
  188. .errnz FL_V_ROUND_DOWN - 8000h
  189. ror bh, 8
  190. sbb edi, eax
  191. sbb ecx, edx
  192. shrd edi, ecx, FLOG2
  193. sar ecx, FLOG2 ; gamma = [ecx:edi] >>= 4
  194. mov eqGamma_hi, ecx
  195. mov eqGamma_lo, edi
  196. mov eax, N0
  197. ; Register state:
  198. ; eax = N0
  199. ; ebx = fl
  200. ; ecx = eqGamma_hi
  201. ; edx = garbage
  202. ; esi = M0
  203. ; edi = eqGamma_lo
  204. testb ebx, FL_FLIP_H
  205. jnz line_runs_right_to_left
  206. ;-----------------------------------------------------------------------;
  207. ; Figure out which pixels are at the ends of a left-to-right line. ;
  208. ; --------> ;
  209. ;-----------------------------------------------------------------------;
  210. public line_runs_left_to_right
  211. line_runs_left_to_right::
  212. or esi, esi
  213. jz short LtoR_check_slope_one
  214. ; skip ahead if M0 == 0
  215. ; (in that case, x0 = 0 which is to be
  216. ; kept in esi, and is already
  217. ; conventiently zero)
  218. or eax, eax
  219. jnz short LtoR_N0_not_zero
  220. .errnz FL_H_ROUND_DOWN - 80h
  221. ror bl, 8
  222. sbb esi, -F/2
  223. shr esi, FLOG2
  224. jmp short LtoR_check_slope_one
  225. ; esi = x0 = rounded M0
  226. LtoR_N0_not_zero:
  227. sub eax, F/2
  228. sbb edx, edx
  229. xor eax, edx
  230. sub eax, edx
  231. cmp esi, eax
  232. sbb esi, esi
  233. inc esi ; esi = x0 = (abs(N0 - F/2) <= M0)
  234. public LtoR_check_slope_one
  235. LtoR_check_slope_one::
  236. mov ulSlopeOneAdjustment, 0
  237. mov eax, ebx
  238. and eax, FL_FLIP_SLOPE_ONE + FL_H_ROUND_DOWN
  239. cmp eax, FL_FLIP_SLOPE_ONE + FL_H_ROUND_DOWN
  240. jne short LtoR_compute_y0_from_x0
  241. ; We have to special case lines that are exactly of slope 1 or -1:
  242. ;
  243. ; if (M1 > 0) AMD (N1 == M1 + 8)
  244. ;
  245. mov eax, N0
  246. add eax, dN
  247. and eax, F - 1 ; eax = N1
  248. mov edx, M0
  249. add edx, dM
  250. and edx, F - 1 ; edx = M1
  251. jz short LtoR_slope_one_check_start_point
  252. add edx, F/2 ; M1 + 8
  253. cmp edx, eax ; cmp N1, M1 + 8
  254. jne short LtoR_slope_one_check_start_point
  255. mov ulSlopeOneAdjustment, -1
  256. LtoR_slope_one_check_start_point:
  257. ;
  258. ; if (M0 > 0) AMD (N0 == M0 + 8)
  259. ;
  260. mov eax, M0
  261. or eax, eax
  262. jz short LtoR_compute_y0_from_x0
  263. add eax, F/2
  264. cmp eax, N0 ; cmp M0 + 8, N0
  265. jne short LtoR_compute_y0_from_x0
  266. xor esi, esi ; x0 = 0
  267. LtoR_compute_y0_from_x0:
  268. ; ecx = eqGamma_hi
  269. ; esi = x0
  270. ; edi = eqGamma_lo
  271. mov eax, dN
  272. mov edx, dM
  273. mov x0, esi
  274. mov y0, 0
  275. cmp ecx, 0
  276. jl short LtoR_compute_x1
  277. neg esi
  278. and esi, eax
  279. sub edx, esi
  280. cmp edi, edx
  281. mov edx, dM
  282. jb short LtoR_compute_x1 ; Bug fix: Must be unsigned!
  283. mov y0, 1 ; y0 = floor((dN * x0 + eqGamma) / dM)
  284. LtoR_compute_x1:
  285. ; Register state:
  286. ; eax = dN
  287. ; ebx = fl
  288. ; ecx = garbage
  289. ; edx = dM
  290. ; esi = garbage
  291. ; edi = garbage
  292. mov esi, M0
  293. add esi, edx
  294. mov ecx, esi
  295. shr esi, FLOG2
  296. dec esi ; x1 = ((M0 + dM) >> 4) - 1
  297. add esi, ulSlopeOneAdjustment
  298. and ecx, F-1 ; M1 = (M0 + dM) & 15
  299. jz done_first_pel_last_pel
  300. add eax, N0
  301. and eax, F-1 ; N1 = (N0 + dN) & 15
  302. jnz short LtoR_N1_not_zero
  303. .errnz FL_H_ROUND_DOWN - 80h
  304. ror bl, 8
  305. sbb ecx, -F/2
  306. shr ecx, FLOG2 ; ecx = LROUND(M1, fl & FL_ROUND_DOWN)
  307. add esi, ecx
  308. jmp done_first_pel_last_pel
  309. LtoR_N1_not_zero:
  310. sub eax, F/2
  311. sbb edx, edx
  312. xor eax, edx
  313. sub eax, edx
  314. cmp eax, ecx
  315. jg done_first_pel_last_pel
  316. inc esi
  317. jmp done_first_pel_last_pel
  318. ;-----------------------------------------------------------------------;
  319. ; Figure out which pixels are at the ends of a right-to-left line. ;
  320. ; <-------- ;
  321. ;-----------------------------------------------------------------------;
  322. ; Compute x0:
  323. public line_runs_right_to_left
  324. line_runs_right_to_left::
  325. mov x0, 1 ; x0 = 1
  326. or eax, eax
  327. jnz short RtoL_N0_not_zero
  328. xor edx, edx ; ulDelta = 0
  329. .errnz FL_H_ROUND_DOWN - 80h
  330. ror bl, 8
  331. sbb esi, -F/2
  332. shr esi, FLOG2 ; esi = LROUND(M0, fl & FL_H_ROUND_DOWN)
  333. jz short RtoL_check_slope_one
  334. mov x0, 2
  335. mov edx, dN
  336. jmp short RtoL_check_slope_one
  337. RtoL_N0_not_zero:
  338. sub eax, F/2
  339. sbb edx, edx
  340. xor eax, edx
  341. sub eax, edx
  342. add eax, esi ; eax = ABS(N0 - F/2) + M0
  343. xor edx, edx ; ulDelta = 0
  344. cmp eax, F
  345. jle short RtoL_check_slope_one
  346. mov x0, 2 ; x0 = 2
  347. mov edx, dN ; ulDelta = dN
  348. public RtoL_check_slope_one
  349. RtoL_check_slope_one::
  350. mov ulSlopeOneAdjustment, 0
  351. mov eax, ebx
  352. and eax, FL_FLIP_SLOPE_ONE + FL_H_ROUND_DOWN
  353. cmp eax, FL_FLIP_SLOPE_ONE
  354. jne short RtoL_compute_y0_from_x0
  355. ; We have to special case lines that are exactly of slope 1 or -1:
  356. ;
  357. ; if ((N1 > 0) && (M1 == N1 + 8))
  358. ;
  359. mov eax, N0
  360. add eax, dN
  361. and eax, F - 1 ; eax = N1
  362. jz short RtoL_slope_one_check_start_point
  363. mov esi, M0
  364. add esi, dM
  365. and esi, F - 1 ; esi = M1
  366. add eax, F/2 ; N1 + 8
  367. cmp esi, eax ; cmp M1, N1 + 8
  368. jne short RtoL_slope_one_check_start_point
  369. mov ulSlopeOneAdjustment, 1
  370. RtoL_slope_one_check_start_point:
  371. ;
  372. ; if ((N0 > 0) && (M0 == N0 + 8))
  373. ;
  374. mov eax,N0 ; eax = N0
  375. or eax,eax ; check for N0 == 0
  376. jz short RtoL_compute_y0_from_x0
  377. mov esi, M0 ; esi = M0
  378. add eax, F/2 ; N0 + 8
  379. cmp eax, esi ; cmp M0 , N0 + 8
  380. jne short RtoL_compute_y0_from_x0
  381. mov x0, 2 ; x0 = 2
  382. mov edx, dN ; ulDelta = dN
  383. RtoL_compute_y0_from_x0:
  384. ; eax = garbage
  385. ; ebx = fl
  386. ; ecx = eqGamma_hi
  387. ; edx = ulDelta
  388. ; esi = garbage
  389. ; edi = eqGamma_lo
  390. mov eax, dN ; eax = dN
  391. mov y0, 0 ; y0 = 0
  392. add edi, edx
  393. adc ecx, 0 ; eqGamma += ulDelta
  394. ; NOTE: Setting flags here!
  395. mov edx, dM ; edx = dM
  396. jl short RtoL_compute_x1 ; NOTE: Looking at the flags here!
  397. jg short RtoL_y0_is_2
  398. lea ecx, [edx + edx]
  399. sub ecx, eax ; ecx = 2 * dM - dN
  400. cmp edi, ecx
  401. jae short RtoL_y0_is_2 ; Bug fix: Must be unsigned!
  402. sub ecx, edx ; ecx = dM - dN
  403. cmp edi, ecx
  404. jb short RtoL_compute_x1 ; Bug fix: Must be unsigned!
  405. mov y0, 1
  406. jmp short RtoL_compute_x1
  407. RtoL_y0_is_2:
  408. mov y0, 2
  409. RtoL_compute_x1:
  410. ; Register state:
  411. ; eax = dN
  412. ; ebx = fl
  413. ; ecx = garbage
  414. ; edx = dM
  415. ; esi = garbage
  416. ; edi = garbage
  417. mov esi, M0
  418. add esi, edx
  419. mov ecx, esi
  420. shr esi, FLOG2 ; x1 = (M0 + dM) >> 4
  421. add esi, ulSlopeOneAdjustment
  422. and ecx, F-1 ; M1 = (M0 + dM) & 15
  423. add eax, N0
  424. and eax, F-1 ; N1 = (N0 + dN) & 15
  425. jnz short RtoL_N1_not_zero
  426. .errnz FL_H_ROUND_DOWN - 80h
  427. ror bl, 8
  428. sbb ecx, -F/2
  429. shr ecx, FLOG2 ; ecx = LROUND(M1, fl & FL_ROUND_DOWN)
  430. add esi, ecx
  431. jmp done_first_pel_last_pel
  432. RtoL_N1_not_zero:
  433. sub eax, F/2
  434. sbb edx, edx
  435. xor eax, edx
  436. sub eax, edx
  437. add eax, ecx ; eax = ABS(N1 - F/2) + M1
  438. cmp eax, F+1
  439. sbb esi, -1
  440. done_first_pel_last_pel:
  441. ; Register state:
  442. ; eax = garbage
  443. ; ebx = fl
  444. ; ecx = garbage
  445. ; edx = garbage
  446. ; esi = x1
  447. ; edi = garbage
  448. mov ecx, x0
  449. lea edx, [esi + 1]
  450. sub edx, ecx ; edx = x1 - x0 + 1
  451. jle next_line
  452. mov cStylePels, edx
  453. mov xStart, ecx
  454. ;-----------------------------------------------------------------------;
  455. ; See if clipping or styling needs to be done. ;
  456. ;-----------------------------------------------------------------------;
  457. testb ebx, FL_CLIP
  458. jnz do_some_clipping
  459. ; Register state:
  460. ; eax = garbage
  461. ; ebx = fl
  462. ; ecx = x0
  463. ; edx = garbage
  464. ; esi = x1
  465. ; edi = garbage
  466. done_clipping:
  467. mov eax, y0
  468. sub esi, ecx
  469. inc esi ; esi = cPels = x1 - x0 + 1
  470. mov cPels, esi
  471. add ecx, x ; ecx = ptlStart.ptl_x
  472. add eax, y ; eax = ptlStart.ptl_y
  473. testb ebx, FL_FLIP_D
  474. jz short do_v_unflip
  475. xchg ecx, eax
  476. do_v_unflip:
  477. testb ebx, FL_FLIP_V
  478. jz short done_unflips
  479. neg eax
  480. done_unflips:
  481. testb ebx, FL_STYLED
  482. jnz do_some_styling
  483. done_styling:
  484. lea edx, [strip.ST_alStrips + (STRIP_MAX * 4)]
  485. mov plStripEnd, edx
  486. ;-----------------------------------------------------------------------;
  487. ; Setup to do DDA. ;
  488. ;-----------------------------------------------------------------------;
  489. ; Register state:
  490. ; eax = ptlStart.ptl_y
  491. ; ebx = fl
  492. ; ecx = ptlStart.ptl_x
  493. ; edx = garbage
  494. ; esi = garbage
  495. ; edi = garbage
  496. mov strip.ST_ptlStart.ptl_x, ecx
  497. mov strip.ST_ptlStart.ptl_y, eax
  498. mov eax, dM
  499. mov ecx, dN
  500. mov esi, eqGamma_lo
  501. mov edi, eqGamma_hi
  502. ; Register state:
  503. ; eax = dM
  504. ; ebx = fl
  505. ; ecx = dN
  506. ; edx = garbage
  507. ; esi = eqGamma_lo
  508. ; edi = eqGamma_hi
  509. lea edx, [ecx + ecx] ; if (2 * dN > dM)
  510. cmp edx, eax
  511. mov edx, y0 ; Load y0 again
  512. jbe short after_half_flip
  513. test ebx, (FL_STYLED + FL_DONT_DO_HALF_FLIP)
  514. jnz short after_half_flip
  515. or ebx, FL_FLIP_HALF
  516. mov fl, ebx
  517. ; Do a half flip!
  518. not esi
  519. not edi
  520. add esi, eax
  521. adc edi, 0 ; eqGamma = -eqGamma - 1 + dM
  522. neg ecx
  523. add ecx, eax ; dN = dM - dN
  524. neg edx
  525. add edx, x0 ; y0 = x0 - y0
  526. after_half_flip:
  527. mov strip.ST_flFlips, ebx
  528. mov eax, dM
  529. ; Register state:
  530. ; eax = dM
  531. ; ebx = fl
  532. ; ecx = dN
  533. ; edx = y0
  534. ; esi = eqGamma_lo
  535. ; edi = eqGamma_hi
  536. or ecx, ecx
  537. jz short zero_slope
  538. compute_dda_stuff:
  539. inc edx
  540. mul edx
  541. stc ; set the carry to accomplish -1
  542. sbb eax, esi
  543. sbb edx, edi ; (y0 + 1) * dM - eqGamma - 1
  544. div ecx
  545. mov esi, eax ; esi = i
  546. mov edi, edx ; edi = r
  547. xor edx, edx
  548. mov eax, dM
  549. div ecx ; edx = d_R, eax = d_I
  550. mov d_I, eax
  551. sub esi, x0
  552. inc esi
  553. done_dda_stuff:
  554. ; Register state:
  555. ; eax = d_I
  556. ; ebx = fl
  557. ; ecx = dN
  558. ; edx = d_R
  559. ; esi = i
  560. ; edi = r
  561. ; We're going to decide if we can call the short-vector routines. They
  562. ; can only take strips that have a maximum length of 15 pixels each.
  563. ; We happen to know that the longest strip in our line could be is d_I + 1.
  564. and ebx, FL_STRIP_MASK
  565. mov eax, apfn
  566. .errnz FL_STRIP_SHIFT
  567. lea eax, [eax + ebx * 4]
  568. cmp d_I, MAX_SHORT_STROKE_LENGTH
  569. sbb ebx, ebx ; ffffffffh when < 15, 0 when >= 15
  570. and ebx, NUM_STRIP_DRAW_DIRECTIONS * 4
  571. ; Look four entries further into table
  572. mov eax, [eax + ebx]
  573. mov pfn, eax
  574. lea eax, [strip.ST_alStrips]
  575. mov ebx, cPels
  576. ;-----------------------------------------------------------------------;
  577. ; Do our main DDA loop. ;
  578. ;-----------------------------------------------------------------------;
  579. ; Register state:
  580. ; eax = plStrip
  581. ; ebx = cPels
  582. ; ecx = dN
  583. ; edx = d_R
  584. ; esi = i
  585. ; edi = r
  586. dda_loop:
  587. sub ebx, esi
  588. jle final_strip
  589. mov [eax], esi
  590. add eax, 4
  591. cmp plStripEnd, eax
  592. jbe short output_strips
  593. done_output_strips:
  594. mov esi, d_I
  595. add edi, edx
  596. cmp edi, ecx
  597. jb short dda_loop
  598. sub edi, ecx
  599. inc esi
  600. jmp short dda_loop
  601. zero_slope:
  602. mov esi, 7fffffffh ; Make run maximum length (cPels
  603. ; actually decideds how long the line
  604. ; is)
  605. mov d_I, 7fffffffh ; Make delta maximum length so that
  606. ; we don't try to do short vectors
  607. mov eax, cPels ; We need this when we decide if to do
  608. dec eax ; short strip routines.
  609. jmp short done_dda_stuff
  610. ;-----------------------------------------------------------------------;
  611. ; Empty strips buffer. ;
  612. ;-----------------------------------------------------------------------;
  613. output_strips:
  614. mov d_R, edx
  615. mov cPels, ebx
  616. mov i, esi
  617. mov r, edi
  618. mov dN, ecx
  619. lea edx, [strip.ST_alStrips]
  620. sub eax, edx
  621. shr eax, 2
  622. mov strip.ST_cStrips, eax
  623. mov eax, ppdev
  624. lea edx, [strip]
  625. mov ecx, pls
  626. ptrCall <dword ptr pfn>, \
  627. <eax, edx, ecx>
  628. mov esi, i
  629. mov edi, r
  630. mov ebx, cPels
  631. mov edx, d_R
  632. mov ecx, dN
  633. lea eax, [strip.ST_alStrips]
  634. jmp done_output_strips
  635. ;-----------------------------------------------------------------------;
  636. ; Empty strips buffer and go on to next line. ;
  637. ;-----------------------------------------------------------------------;
  638. final_strip:
  639. add ebx, esi
  640. mov [eax], ebx
  641. add eax, 4
  642. very_final_strip:
  643. lea edx, [strip.ST_alStrips]
  644. sub eax, edx
  645. shr eax, 2
  646. mov strip.ST_cStrips, eax
  647. mov eax, ppdev
  648. lea edx, [strip]
  649. mov ecx, pls
  650. ptrCall <dword ptr pfn>, \
  651. <eax, edx, ecx>
  652. next_line:
  653. mov ebx, flStart
  654. testb ebx, FL_COMPLEX_CLIP
  655. jnz short see_if_done_complex_clipping
  656. mov edx, pptfxBuf
  657. cmp edx, pptfxBufEnd
  658. je short all_done
  659. mov esi, [edx].ptl_x
  660. mov ecx, [edx].ptl_y
  661. add edx, size POINTL
  662. mov pptfxBuf, edx
  663. mov eax, [edx].ptl_x
  664. mov edi, [edx].ptl_y
  665. jmp the_main_loop
  666. all_done:
  667. mov eax, 1
  668. cRet bLines
  669. see_if_done_complex_clipping:
  670. mov ebx, fl
  671. dec cptfx
  672. jz short all_done
  673. jmp continue_complex_clipping
  674. ;---------------------------Private-Routine-----------------------------;
  675. ; do_some_styling
  676. ;
  677. ; Inputs:
  678. ; eax = ptlStart.ptl_y
  679. ; ebx = fl
  680. ; ecx = ptlStart.ptl_x
  681. ; Preserves:
  682. ; eax, ebx, ecx
  683. ; Output:
  684. ; Exits to done_styling.
  685. ;
  686. ;-----------------------------------------------------------------------;
  687. do_some_styling:
  688. mov ptlStart.ptl_x, ecx
  689. mov esi, pls
  690. mov edi, [esi].LS_spNext ; spThis
  691. mov edx, edi
  692. add edx, cStylePels ; spNext
  693. ; For styles, we don't bother to keep the style position normalized.
  694. ; (we do ensure that it's positive, though). If a figure is over 2
  695. ; billion pels long, we'll be a pel off in our style state (oops!).
  696. and edx, 7fffffffh
  697. mov [esi].LS_spNext, edx
  698. mov ptlStart.ptl_y, eax
  699. ; Do arbitrary styles:
  700. do_arbitrary_style:
  701. testb ebx, FL_FLIP_H
  702. jz short arbitrary_left_to_right
  703. sub edx, x0
  704. add edx, xStart
  705. mov eax, edx
  706. xor edx, edx
  707. div [esi].LS_spTotal
  708. neg edx
  709. jge short continue_right_to_left
  710. add edx, [esi].LS_spTotal
  711. not eax
  712. continue_right_to_left:
  713. mov edi, dword ptr [esi].LS_jStartMask
  714. not edi
  715. mov ecx, [esi].LS_aspRtoL
  716. jmp short compute_arbitrary_stuff
  717. arbitrary_left_to_right:
  718. add edi, x0
  719. sub edi, xStart
  720. mov eax, edi
  721. xor edx, edx
  722. div [esi].LS_spTotal
  723. mov edi, dword ptr [esi].LS_jStartMask
  724. mov ecx, [esi].LS_aspLtoR
  725. compute_arbitrary_stuff:
  726. ; eax = sp / spTotal
  727. ; ebx = fl
  728. ; ecx = pspStart
  729. ; edx = sp % spTotal
  730. ; esi = pla
  731. ; edi = jStyleMask
  732. and eax, [esi].LS_cStyle ; if odd length style and second run
  733. and al, 1 ; through style array, flip the
  734. jz short odd_style_array_done ; meaning of the elements
  735. not edi
  736. odd_style_array_done:
  737. mov [esi].LS_pspStart, ecx
  738. mov eax, [esi].LS_cStyle
  739. lea eax, [ecx + eax * 4 - 4]
  740. mov [esi].LS_pspEnd, eax
  741. find_psp:
  742. sub edx, [ecx]
  743. jl short found_psp
  744. add ecx, 4
  745. jmp short find_psp
  746. found_psp:
  747. mov [esi].LS_psp, ecx
  748. neg edx
  749. mov [esi].LS_spRemaining, edx
  750. sub ecx, [esi].LS_pspStart
  751. test ecx, 4 ; size STYLEPOS
  752. jz short done_arbitrary
  753. not edi
  754. done_arbitrary:
  755. mov dword ptr [esi].LS_jStyleMask, edi
  756. mov eax, ptlStart.ptl_y
  757. mov ecx, ptlStart.ptl_x
  758. jmp done_styling
  759. ;---------------------------Private-Routine-----------------------------;
  760. ; do_some_clipping
  761. ;
  762. ; Inputs:
  763. ; eax = garbage
  764. ; ebx = fl
  765. ; ecx = x0
  766. ; edx = garbage
  767. ; esi = x1
  768. ; edi = garbage
  769. ;
  770. ; Decides whether to do simple or complex clipping.
  771. ;
  772. ;-----------------------------------------------------------------------;
  773. align 4
  774. public do_some_clipping
  775. do_some_clipping::
  776. testb ebx, FL_COMPLEX_CLIP
  777. jnz initialize_complex_clipping
  778. ;-----------------------------------------------------------------------;
  779. ; simple_clipping
  780. ;
  781. ; Inputs:
  782. ; ebx = fl
  783. ; ecx = x0
  784. ; esi = x1
  785. ; Output:
  786. ; ebx = fl
  787. ; ecx = new x0 (stack variable updated too)
  788. ; esi = new x1
  789. ; y0 stack variable updated
  790. ; Uses:
  791. ; All registers
  792. ; Exits:
  793. ; to done_clipping
  794. ;
  795. ; This routine handles clipping the line to the clip rectangle (it's
  796. ; faster to handle this case in the driver than to call the engine to
  797. ; clip for us).
  798. ;
  799. ; Fractional end-point lines complicate our lives a bit when doing
  800. ; clipping:
  801. ;
  802. ; 1) For styling, we must know the unclipped line's length in pels, so
  803. ; that we can correctly update the styling state when the line is
  804. ; clipped. For this reason, I do clipping after doing the hard work
  805. ; of figuring out which pixels are at the ends of the line (this is
  806. ; wasted work if the line is not styled and is completely clipped,
  807. ; but I think it's simpler this way). Another reason is that we'll
  808. ; have calculated eqGamma already, which we use for the intercept
  809. ; calculations.
  810. ;
  811. ; With the assumption that most lines will not be completely clipped
  812. ; away, this strategy isn't too painful.
  813. ;
  814. ; 2) x0, y0 are not necessarily zero, where (x0, y0) is the start pel of
  815. ; the line.
  816. ;
  817. ; 3) We know x0, y0 and x1, but not y1. We haven't needed to calculate
  818. ; y1 until now. We'll need the actual value, and not an upper bound
  819. ; like y1 = LFLOOR(dM) + 2 because we have to be careful when
  820. ; calculating x(y) that y0 <= y <= y1, otherwise we can cause an
  821. ; overflow on the divide (which, needless to say, is bad).
  822. ;
  823. ;-----------------------------------------------------------------------;
  824. public simple_clipping
  825. simple_clipping::
  826. mov edi, prclClip ; get pointer to normalized clip rect
  827. and ebx, FL_RECTLCLIP_MASK ; (it's lower-right exclusive)
  828. .errnz (FL_RECTLCLIP_SHIFT - 2); ((ebx AND FL_RECTLCLIP_MASK) shr
  829. .errnz (size RECTL) - 16 ; FL_RECTLCLIP_SHIFT) is our index
  830. lea edi, [edi + ebx*4] ; into the array of rectangles
  831. mov edx, [edi].xRight ; load the rect coordinates
  832. mov eax, [edi].xLeft
  833. mov ebx, [edi].yBottom
  834. mov edi, [edi].yTop
  835. ; Translate to our origin and so some quick completely clipped tests:
  836. sub edx, x
  837. cmp ecx, edx
  838. jge totally_clipped ; totally clipped if x0 >= xRight
  839. sub eax, x
  840. cmp esi, eax
  841. jl totally_clipped ; totally clipped if x1 < xLeft
  842. sub ebx, y
  843. cmp y0, ebx
  844. jge totally_clipped ; totally clipped if y0 >= yBottom
  845. sub edi, y
  846. ; Save some state:
  847. mov xClipRight, edx
  848. mov xClipLeft, eax
  849. cmp esi, edx ; if (x1 >= xRight) x1 = xRight - 1
  850. jl short calculate_y1
  851. lea esi, [edx - 1]
  852. calculate_y1:
  853. mov eax, esi ; y1 = (x1 * dN + eqGamma) / dM
  854. mul dN
  855. add eax, eqGamma_lo
  856. adc edx, eqGamma_hi
  857. div dM
  858. cmp edi, eax ; if (yTop > y1) clipped
  859. jg short totally_clipped
  860. cmp ebx, eax ; if (yBottom > y1) know x1
  861. jg short x1_computed
  862. mov eax, ebx ; x1 = (yBottom * dM + eqBeta) / dN
  863. mul dM
  864. stc
  865. sbb eax, eqGamma_lo
  866. sbb edx, eqGamma_hi
  867. div dN
  868. mov esi, eax
  869. ; At this point, we've taken care of calculating the intercepts with the
  870. ; right and bottom edges. Now we work on the left and top edges:
  871. x1_computed:
  872. mov edx, y0
  873. mov eax, xClipLeft ; don't have to compute y intercept
  874. cmp eax, ecx ; at left edge if line starts to
  875. jle short top_intercept ; right of left edge
  876. mov ecx, eax ; x0 = xLeft
  877. mul dN ; y0 = (xLeft * dN + eqGamma) / dM
  878. add eax, eqGamma_lo
  879. adc edx, eqGamma_hi
  880. div dM
  881. cmp ebx, eax ; if (yBottom <= y0) clipped
  882. jle short totally_clipped
  883. mov edx, eax
  884. mov y0, eax
  885. top_intercept:
  886. mov ebx, fl ; get ready to leave
  887. mov x0, ecx
  888. cmp edi, edx ; if (yTop <= y0) done clipping
  889. jle done_clipping
  890. mov eax, edi ; x0 = (yTop * dM + eqBeta) / dN + 1
  891. mul dM
  892. stc
  893. sbb eax, eqGamma_lo
  894. sbb edx, eqGamma_hi
  895. div dN
  896. lea ecx, [eax + 1]
  897. cmp xClipRight, ecx ; if (xRight <= x0) clipped
  898. jle short totally_clipped
  899. mov y0, edi ; y0 = yTop
  900. mov x0, ecx
  901. jmp done_clipping ; all done!
  902. totally_clipped:
  903. ; The line is completely clipped. See if we have to update our style state:
  904. mov ebx, fl
  905. testb ebx, FL_STYLED
  906. jz next_line
  907. ; Adjust our style state:
  908. mov esi, pls
  909. mov eax, [esi].LS_spNext
  910. add eax, cStylePels
  911. mov [esi].LS_spNext, eax
  912. cmp eax, [esi].LS_spTotal2
  913. jb next_line
  914. ; Have to normalize first:
  915. xor edx, edx
  916. div [esi].LS_spTotal2
  917. mov [esi].LS_spNext, edx
  918. jmp next_line
  919. ;-----------------------------------------------------------------------;
  920. initialize_complex_clipping:
  921. mov eax, dN ; save a copy of original dN
  922. mov dN_Original, eax
  923. ;---------------------------Private-Routine-----------------------------;
  924. ; continue_complex_clipping
  925. ;
  926. ; Inputs:
  927. ; ebx = fl
  928. ; Output:
  929. ; ebx = fl
  930. ; ecx = x0
  931. ; esi = x1
  932. ; Uses:
  933. ; All registers.
  934. ; Exits:
  935. ; to done_clipping
  936. ;
  937. ; This routine handles the necessary initialization for the next
  938. ; run in the CLIPLINE structure.
  939. ;
  940. ; NOTE: This routine is jumped to from two places!
  941. ;-----------------------------------------------------------------------;
  942. public continue_complex_clipping
  943. continue_complex_clipping::
  944. mov edi, prun
  945. mov ecx, xStart
  946. testb ebx, FL_FLIP_H
  947. jz short complex_left_to_right
  948. complex_right_to_left:
  949. ; Figure out x0 and x1 for right-to-left lines:
  950. add ecx, cStylePels
  951. dec ecx
  952. mov esi, ecx ; esi = ecx = xStart + cStylePels - 1
  953. sub ecx, [edi].RUN_iStop ; New x0
  954. sub esi, [edi].RUN_iStart ; New x1
  955. jmp short complex_reset_variables
  956. complex_left_to_right:
  957. ; Figure out x0 and x1 for left-to-right lines:
  958. mov esi, ecx ; esi = ecx = xStart
  959. add ecx, [edi].RUN_iStart ; New x0
  960. add esi, [edi].RUN_iStop ; New x1
  961. complex_reset_variables:
  962. mov x0, ecx
  963. ; The half flip mucks with some of our variables, and we have to reset
  964. ; them every pass. We would have to reset eqGamma too, but it never
  965. ; got saved to memory in its modified form.
  966. add edi, size RUN
  967. mov prun, edi ; Increment run pointer for next time
  968. mov edi, pls
  969. mov eax, [edi].LS_spComplex
  970. mov [edi].LS_spNext, eax ; pls->spNext = pls->spComplex
  971. mov eax, dN_Original ; dN = dN_Original
  972. mov dN, eax
  973. mul ecx
  974. add eax, eqGamma_lo
  975. adc edx, eqGamma_hi ; [edx:eax] = dN*x0 + eqGamma
  976. div dM
  977. mov y0, eax
  978. jmp done_clipping
  979. endProc bLines
  980. end