FILLQUAD.ASM 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. ;
  2. ; Command & Conquer Red Alert(tm)
  3. ; Copyright 2025 Electronic Arts Inc.
  4. ;
  5. ; This program is free software: you can redistribute it and/or modify
  6. ; it under the terms of the GNU General Public License as published by
  7. ; the Free Software Foundation, either version 3 of the License, or
  8. ; (at your option) any later version.
  9. ;
  10. ; This program is distributed in the hope that it will be useful,
  11. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ; GNU General Public License for more details.
  14. ;
  15. ; You should have received a copy of the GNU General Public License
  16. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. ;
  18. ;***************************************************************************
  19. ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
  20. ;***************************************************************************
  21. ;* *
  22. ;* Project Name : Westwood 32 bit Library *
  23. ;* *
  24. ;* File Name : FILLQUAD.ASM *
  25. ;* *
  26. ;* Programmer : Ian M. Leslie *
  27. ;* *
  28. ;* Start Date : August 11, 1994 *
  29. ;* *
  30. ;* Last Update : August 30, 1994 [IML] *
  31. ;* *
  32. ;*-------------------------------------------------------------------------*
  33. ;* Functions: *
  34. ;* Fill_Quad -- Flood fills an arbitrary convex quadrilateral *
  35. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  36. IDEAL
  37. P386
  38. MODEL USE32 FLAT
  39. INCLUDE ".\drawbuff.inc"
  40. INCLUDE ".\gbuffer.inc"
  41. SLOT_VACANT EQU 80008000h
  42. NULL EQU 0h
  43. CODESEG
  44. ;***************************************************************************
  45. ;* VVC::FILL_QUAD -- Flood fills an arbitrary convex quadrilateral *
  46. ;* *
  47. ;* INPUT: DWORD this_object - associated graphic viewport *
  48. ;* DWORD span_buff - pointer to span array *
  49. ;* DWORD x0_pixel - the zeroth x pixel position *
  50. ;* DWORD y0_pixel - the zeroth y pixel position *
  51. ;* DWORD x1_pixel - the first x pixel position *
  52. ;* DWORD y1_pixel - the first y pixel position *
  53. ;* DWORD x2_pixel - the second x pixel position *
  54. ;* DWORD y2_pixel - the second y pixel position *
  55. ;* DWORD x3_pixel - the third x pixel position *
  56. ;* DWORD y3_pixel - the third y pixel position *
  57. ;* DWORD color - the color of the quad to fill *
  58. ;* *
  59. ;* Bounds Checking: Compares quad points with the graphic viewport it *
  60. ;* has been assigned to. *
  61. ;* *
  62. ;* Rasterization Rules: FILL_QUAD is designed to be used within a quad *
  63. ;* mesh. There is no pixel overlapping or stitching *
  64. ;* effects at shared borders. FILL_QUAD is NOT *
  65. ;* recommended for isolated quads. * *
  66. ;* HISTORY: *
  67. ;* 08/11/1994 IML : Created. *
  68. ;* 08/26/1994 IML : Various optimizations. *
  69. ;* 08/30/1994 IML : Added rasterization rules for shared borders. *
  70. ;*=========================================================================*
  71. PROC Buffer_Fill_Quad C NEAR
  72. USES eax,ebx,ecx,edx,esi,edi
  73. ;*==================================================================
  74. ;* Define the arguments that the function takes.
  75. ;*==================================================================
  76. ARG this_object:DWORD ; associated graphic viewport
  77. ARG span_buff:DWORD ; pointer to span array
  78. ARG x0_pixel:DWORD ; the zeroth x pixel position
  79. ARG y0_pixel:DWORD ; the zeroth y pixel position
  80. ARG x1_pixel:DWORD ; the first x pixel position
  81. ARG y1_pixel:DWORD ; the first y pixel position
  82. ARG x2_pixel:DWORD ; the second x pixel position
  83. ARG y2_pixel:DWORD ; the second y pixel position
  84. ARG x3_pixel:DWORD ; the third x pixel position
  85. ARG y3_pixel:DWORD ; the third y pixel position
  86. ARG color:DWORD ; the color of the quad
  87. ;*==================================================================
  88. ;* Define the local variables that we will use on the stack.
  89. ;*==================================================================
  90. LOCAL clip_min_x:DWORD ; boundary of viewport
  91. LOCAL clip_max_x:DWORD ;
  92. LOCAL clip_min_y:DWORD ;
  93. LOCAL clip_max_y:DWORD ;
  94. LOCAL clip_var:DWORD
  95. LOCAL left_clip_base:DWORD:2 ; storage for additional edges
  96. LOCAL left_clip_index:DWORD ; generated by clipping
  97. LOCAL right_clip_base:DWORD:2 ;
  98. LOCAL right_clip_index:DWORD ;
  99. LOCAL scanline_min:DWORD ; vertical extent of quad
  100. LOCAL scanline_max:DWORD
  101. LOCAL realignment:DWORD
  102. LOCAL bpr:DWORD ; bytes per row of associated buffer
  103. ;*==================================================================
  104. ;* Extract essential GraphicViewPort info.
  105. ;*==================================================================
  106. mov ebx,[this_object]
  107. mov eax,[(GraphicViewPort ebx).GVPXPos]
  108. mov [clip_min_x],eax
  109. mov eax,[(GraphicViewPort ebx).GVPYPos]
  110. mov [clip_min_y],eax
  111. mov eax,[(GraphicViewPort ebx).GVPWidth]
  112. mov [clip_max_x],eax
  113. add eax,[(GraphicViewPort ebx).GVPXAdd]
  114. add eax,[(GraphicViewPort ebx).GVPPitch]
  115. mov [bpr],eax
  116. mov eax,[(GraphicViewPort ebx).GVPHeight]
  117. mov [clip_max_y],eax
  118. ;*==================================================================
  119. ;* Adjust top and right edges of viewport for rasterization rules.
  120. ;*==================================================================
  121. dec [clip_max_y]
  122. dec [clip_min_y]
  123. ;*==================================================================
  124. ;* Find the vertical extent of the quad BEFORE clipping.
  125. ;* y0_pixel = y0, y1_pixel = y1, y2_pixel = y2, y3_pixel = y3
  126. ;*==================================================================
  127. mov eax,[y0_pixel]
  128. cmp eax,[y1_pixel]
  129. jle short ??y1_not_smaller
  130. mov eax,[y1_pixel]
  131. ??y1_not_smaller:
  132. cmp eax,[y2_pixel]
  133. jle short ??y2_not_smaller
  134. mov eax,[y2_pixel]
  135. ??y2_not_smaller:
  136. cmp eax,[y3_pixel]
  137. jle short ??y3_not_smaller
  138. mov eax,[y3_pixel]
  139. ??y3_not_smaller:
  140. cmp eax,[clip_min_y]
  141. jge short ??no_clamp_min_min
  142. mov eax,[clip_min_y]
  143. ??no_clamp_min_min:
  144. cmp eax,[clip_max_y]
  145. jle short ??no_clamp_max_min
  146. mov eax,[clip_max_y]
  147. ; scanline_min = MIN (y0, y1, y2, y3)
  148. ??no_clamp_max_min: ; scanline_min = MAX (scanline_min, clip_min_y)
  149. mov [scanline_min],eax ; scanline_min = MIN (scanline_min, clip_max_y)
  150. mov eax,[y0_pixel]
  151. cmp eax,[y1_pixel]
  152. jge short ??y1_not_greater
  153. mov eax,[y1_pixel]
  154. ??y1_not_greater:
  155. cmp eax,[y2_pixel]
  156. jge short ??y2_not_greater
  157. mov eax,[y2_pixel]
  158. ??y2_not_greater:
  159. cmp eax,[y3_pixel]
  160. jge short ??y3_not_greater
  161. mov eax,[y3_pixel]
  162. ??y3_not_greater:
  163. cmp eax,[clip_min_y]
  164. jge short ??no_clamp_min_max
  165. mov eax,[clip_min_y]
  166. ??no_clamp_min_max:
  167. cmp eax,[clip_max_y]
  168. jle short ??no_clamp_max_max
  169. mov eax,[clip_max_y]
  170. ; scanline_max = MAX (y0, y1, y2, y3)
  171. ??no_clamp_max_max: ; scanline_max = MAX (scanline_max, clip_min_y)
  172. mov [scanline_max],eax ; scanline_max = MIN (scanline_max, clip_max_y)
  173. ;*==================================================================
  174. ;* Initialize memory for spans.
  175. ;*==================================================================
  176. sub eax,[scanline_min]
  177. je ??abort_fill_quad ; don't render quads with zero height
  178. mov ebx,eax
  179. mov eax,[span_buff] ; check span_buff for NULL ptr
  180. cmp eax,NULL
  181. je ??abort_fill_quad
  182. sal ebx,2
  183. ??span_initialize_loop:
  184. mov [DWORD PTR eax + ebx],SLOT_VACANT
  185. sub ebx,4
  186. jl short ??exit_span_initialize
  187. mov [DWORD PTR eax + ebx],SLOT_VACANT
  188. sub ebx,4
  189. jl short ??exit_span_initialize
  190. mov [DWORD PTR eax + ebx],SLOT_VACANT
  191. sub ebx,4
  192. jl short ??exit_span_initialize
  193. mov [DWORD PTR eax + ebx],SLOT_VACANT
  194. sub ebx,4
  195. jge short ??span_initialize_loop
  196. ;*==================================================================
  197. ;* Clip and scan convert the four edges defining the quad.
  198. ;*==================================================================
  199. ??exit_span_initialize:
  200. mov [left_clip_index],0
  201. mov [right_clip_index],0
  202. mov eax,[x0_pixel]
  203. mov ebx,[y0_pixel]
  204. mov ecx,[x1_pixel]
  205. mov edx,[y1_pixel]
  206. call NEAR PTR ??clip_and_scan_convert
  207. mov eax,[x1_pixel]
  208. mov ebx,[y1_pixel]
  209. mov ecx,[x2_pixel]
  210. mov edx,[y2_pixel]
  211. call NEAR PTR ??clip_and_scan_convert
  212. mov eax,[x2_pixel]
  213. mov ebx,[y2_pixel]
  214. mov ecx,[x3_pixel]
  215. mov edx,[y3_pixel]
  216. call NEAR PTR ??clip_and_scan_convert
  217. mov eax,[x3_pixel]
  218. mov ebx,[y3_pixel]
  219. mov ecx,[x0_pixel]
  220. mov edx,[y0_pixel]
  221. call NEAR PTR ??clip_and_scan_convert
  222. ;*==================================================================
  223. ;* Scan convert up to 2 additional left and right vertical edges
  224. ;* generated by the clipping process.
  225. ;*==================================================================
  226. cmp [left_clip_index],0
  227. je short ??no_left_edge
  228. mov eax,[clip_min_x]
  229. mov ebx,[left_clip_base]
  230. mov ecx,eax
  231. mov edx,[left_clip_base + 4]
  232. call NEAR PTR ??scan_convert
  233. ??no_left_edge:
  234. cmp [right_clip_index],0
  235. je short ??no_right_edge
  236. mov eax,[clip_max_x]
  237. mov ebx,[right_clip_base]
  238. mov ecx,eax
  239. mov edx,[right_clip_base + 4]
  240. call NEAR PTR ??scan_convert
  241. ;*==================================================================
  242. ;* Fill the quad with specified color. Use DWORD copies where
  243. ;* appropriate.
  244. ;*==================================================================
  245. ??no_right_edge:
  246. mov eax,[this_object]
  247. mov edi,[(GraphicViewPort eax).GVPOffset]
  248. mov eax,[scanline_min] ; eax = scanline_min
  249. mov ebx,[scanline_max]
  250. sub ebx,[scanline_min] ; ebx = span count
  251. mov esi,[span_buff] ; esi = address of top span
  252. mul [bpr]
  253. add edi,eax ; edi = address of top scanline
  254. ; containing quad
  255. mov al,[BYTE PTR color] ; extend pixel color into eax ready
  256. mov ah,al ; for DWORD copies
  257. mov edx,eax
  258. shl eax,16
  259. mov ax,dx
  260. cld ; only fill forwards
  261. jmp ??skip_span ; rasterization rule: don't
  262. ; render topmost span
  263. ??quad_fill_loop:
  264. cmp [DWORD PTR esi],SLOT_VACANT ; test for unused spans due to clipping
  265. je ??skip_span
  266. xor ecx,ecx
  267. xor edx,edx
  268. mov cx,[WORD PTR esi]
  269. mov dx,[WORD PTR esi + 2]
  270. sub ecx,edx
  271. push edi
  272. jns short ??not_negative_count
  273. add edi,ecx
  274. neg ecx ; ecx = span width
  275. ??not_negative_count:
  276. add edi,edx ; edi = address of start of span
  277. cmp ecx,OPTIMAL_BYTE_COPY ; does span width justify DWORD copies?
  278. jl short ??byte_copy
  279. mov edx,ecx
  280. mov ecx,edi
  281. and ecx,3 ; if (ecx == 0) edi is already
  282. jz short ??dword_copy_no_alignment ; DWORD aligned
  283. xor ecx,3
  284. inc ecx ; ecx = number of pixels before alignment
  285. sub edx,ecx
  286. rep stosb
  287. ??dword_copy_no_alignment:
  288. mov ecx,edx ; ecx = remaining pixels on span
  289. shr ecx,2 ; copy (ecx / 4) DWORDS
  290. rep stosd
  291. mov ecx,edx
  292. and ecx,3 ; ecx = remaining pixels on span
  293. ??byte_copy:
  294. rep stosb ; byte copy remaining pixels on span
  295. pop edi
  296. ??skip_span:
  297. add edi,[bpr] ; edi = address of start of next scanline
  298. add esi,4 ; esi = address of next span
  299. dec ebx
  300. jge short ??quad_fill_loop ; is span count >= 0?
  301. ??abort_fill_quad:
  302. ret
  303. ;*==================================================================
  304. ;* This is the section that "pushes" the edge into bounds.
  305. ;* I have marked the section with PORTABLE start and end to signify
  306. ;* how much of this routine is 100% portable between graphics modes.
  307. ;* It was just as easy to have variables as it would be for constants
  308. ;* so the global vars clip_min_x, clip_min_y, clip_max_x, clip_max_y
  309. ;* are used to clip the edge (default is the screen).
  310. ;* PORTABLE start.
  311. ;*==================================================================
  312. ;*==================================================================
  313. ;* Clip an edge against the viewport.
  314. ;*==================================================================
  315. ??clip_and_scan_convert:
  316. call NEAR PTR ??set_left_right_bits
  317. xchg eax,ecx
  318. xchg ebx,edx
  319. mov edi,esi
  320. call NEAR PTR ??set_left_right_bits
  321. mov [clip_var],edi
  322. or [clip_var],esi
  323. jz ??clip_up_down ; trivial acceptance?
  324. test edi,esi
  325. jne ??exit ; trivial rejection?
  326. shl esi,2
  327. call [DWORD PTR cs:??clip_tbl+esi]
  328. xchg eax,ecx
  329. xchg ebx,edx
  330. shl edi,2
  331. call [DWORD PTR cs:??clip_tbl+edi]
  332. ??clip_up_down:
  333. call NEAR PTR ??set_up_down_bits
  334. xchg eax,ecx
  335. xchg ebx,edx
  336. mov edi,esi
  337. call NEAR PTR ??set_up_down_bits
  338. mov [clip_var],edi
  339. or [clip_var],esi
  340. jz ??scan_convert ; trivial acceptance?
  341. test edi,esi
  342. jne ??exit ; trivial rejection?
  343. shl esi,2
  344. call [DWORD PTR cs:??clip_tbl+esi]
  345. xchg eax,ecx
  346. xchg ebx,edx
  347. shl edi,2
  348. call [DWORD PTR cs:??clip_tbl+edi]
  349. jmp ??scan_convert
  350. ;*==================================================================
  351. ;* Subroutine table for clipping conditions.
  352. ;*==================================================================
  353. ??clip_tbl DD ??nada,??a_lft,??a_rgt,??nada
  354. DD ??a_up,??nada,??nada,??nada
  355. DD ??a_dwn
  356. ;*==================================================================
  357. ;* Subroutines for clipping conditions.
  358. ;*==================================================================
  359. ??nada:
  360. retn
  361. ??a_up:
  362. mov esi,[clip_min_y]
  363. call NEAR PTR ??clip_vert
  364. retn
  365. ??a_dwn:
  366. mov esi,[clip_max_y]
  367. call NEAR PTR ??clip_vert
  368. retn
  369. ??a_lft:
  370. mov esi,[clip_min_x]
  371. call NEAR PTR ??clip_horiz
  372. push ebx
  373. mov esi,[left_clip_index]
  374. cmp ebx,[clip_min_y]
  375. jge ??no_left_min_clip
  376. mov ebx,[clip_min_y]
  377. ??no_left_min_clip:
  378. cmp ebx,[clip_max_y]
  379. jle ??no_left_max_clip
  380. mov ebx,[clip_max_y]
  381. ??no_left_max_clip:
  382. mov [left_clip_base + esi],ebx ; a left edge will be generated
  383. mov [left_clip_index],4 ; store off yb
  384. pop ebx
  385. retn
  386. ??a_rgt:
  387. mov esi,[clip_max_x]
  388. call NEAR PTR ??clip_horiz
  389. push ebx
  390. mov esi,[right_clip_index]
  391. cmp ebx,[clip_min_y]
  392. jge ??no_right_min_clip
  393. mov ebx,[clip_min_y]
  394. ??no_right_min_clip:
  395. cmp ebx,[clip_max_y]
  396. jle ??no_right_max_clip
  397. mov ebx,[clip_max_y]
  398. ??no_right_max_clip:
  399. mov [right_clip_base + esi],ebx ; a right edge will be generated
  400. mov [right_clip_index],4 ; store off yb
  401. pop ebx
  402. retn
  403. ;*==================================================================
  404. ;* Clip a line against a horizontal edge at clip_y.
  405. ;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)
  406. ;* xa' = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]
  407. ;* ya' = clip_y
  408. ;*==================================================================
  409. ??clip_vert:
  410. push edx
  411. push eax
  412. mov [clip_var],edx ; clip_var = yb
  413. sub [clip_var],ebx ; clip_var = (yb-ya)
  414. neg eax ; eax = -xa
  415. add eax,ecx ; eax = (xb-xa)
  416. mov edx,esi ; edx = clip_y
  417. sub edx,ebx ; edx = (clip_y-ya)
  418. imul edx ; eax = (clip_y-ya)(xb-xa)
  419. idiv [clip_var] ; eax = (clip_y-ya)(xb-xa)/(yb-ya)
  420. pop edx
  421. add eax,edx ; eax = xa+[(clip_y-ya)(xb-xa)/(yb-ya)]
  422. pop edx
  423. mov ebx,esi ; ebx = clip_y
  424. retn
  425. ;*==================================================================
  426. ;* Clip a line against a vertical edge at clip_x.
  427. ;* (eax,ebxx) = (xa,ya), (ecx,edxx) = (xb,yb)
  428. ;* ya' = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]
  429. ;* xa' = clip_x
  430. ;*==================================================================
  431. ??clip_horiz:
  432. push edx
  433. mov [clip_var],ecx ; clip_var = xb
  434. sub [clip_var],eax ; clip_var = (xb-xa)
  435. sub edx,ebx ; edx = (yb-ya)
  436. neg eax ; eax = -xa
  437. add eax,esi ; eax = (clip_x-xa)
  438. imul edx ; eax = (clip_x-xa)(yb-ya)
  439. idiv [clip_var] ; eax = (clip_x-xa)(yb-ya)/(xb-xa)
  440. add ebx,eax ; ebx = ya+[(clip_x-xa)(yb-ya)/(xb-xa)]
  441. pop edx
  442. mov eax,esi ; eax = clip_x
  443. retn
  444. ;*==================================================================
  445. ;* Set the condition bits for the subroutine table.
  446. ;*==================================================================
  447. ??set_left_right_bits:
  448. xor esi,esi
  449. cmp eax,[clip_min_x] ; if x >= left its not left
  450. jge short ??a_not_left
  451. or esi,1
  452. ??a_not_left:
  453. cmp eax,[clip_max_x] ; if x <= right its not right
  454. jle short ??a_not_right
  455. or esi,2
  456. ??a_not_right:
  457. retn
  458. ??set_up_down_bits:
  459. xor esi,esi
  460. cmp ebx,[clip_min_y] ; if y >= top its not up
  461. jge short ??a_not_up
  462. or esi,4
  463. ??a_not_up:
  464. cmp ebx,[clip_max_y] ; if y <= bottom its not down
  465. jle short ??a_not_down
  466. or esi,8
  467. ??a_not_down:
  468. retn
  469. ;*==================================================================
  470. ;* PORTABLE end.
  471. ;*==================================================================
  472. ;*==================================================================
  473. ;* Scan convert an edge.
  474. ;* (eax,ebx) = (xa,ya), (ecx,edx) = (xb,yb)
  475. ;*==================================================================
  476. ??scan_convert:
  477. cmp ebx,edx
  478. je ??exit ; if (ya == yb) don't scan convert
  479. jl short ??no_swap ; if (ya < yb) swap vertices
  480. xchg eax,ecx
  481. xchg ebx,edx
  482. ??no_swap:
  483. sub edx,ebx ; edx = (yb - ya)
  484. sub ebx,[scanline_min]
  485. sal ebx,2
  486. add ebx,[span_buff] ; ebx = span_buff + 4(ya - clip_min_y)
  487. sub ecx,eax ; ecx = (xb - xa)
  488. je ??v_scan ; if the edge is vertical use a
  489. ; special case routine
  490. push eax
  491. mov eax,ecx ; eax = (xb - xa)
  492. mov ecx,edx ; ecx = (yb - ya)
  493. sal edx,1
  494. mov [realignment],edx ; realignment = 2(yb - ya)
  495. cwd
  496. idiv cx
  497. cwde
  498. movsx edx,dx
  499. mov edi,eax ; edi = (xb - xa) / (yb - ya)
  500. mov esi,edx
  501. mov edx,ecx
  502. pop eax ; eax = xa
  503. neg edx ; edx = -(yb - ya)
  504. sal esi,1 ; esi = 2[(xb - xa) % (yb - ya)]
  505. jns short ??r_scan ; scan to the left or right?
  506. neg esi
  507. ;*==================================================================
  508. ;* Edge scan conversion DDA moving down and to the left.
  509. ;* eax = xpos, ebx = span to reference
  510. ;*==================================================================
  511. cmp ebx,[span_buff]
  512. jg ??l_scan_convert
  513. ??l_scan_convert_loop:
  514. cmp [DWORD PTR ebx],SLOT_VACANT ; if the left slot of span is
  515. jne short ??l_next_slot ; vacant fill it with xpos
  516. mov [ebx],ax
  517. ??l_next_slot:
  518. mov [ebx + 2],ax ; otherwise fill the right slot
  519. ; with xpos
  520. ??l_scan_convert:
  521. dec ecx
  522. jl short ??exit
  523. add ebx,4
  524. add eax,edi
  525. add edx,esi
  526. jle short ??l_scan_convert_loop
  527. dec eax
  528. sub edx,[realignment]
  529. jmp ??l_scan_convert_loop
  530. ;*==================================================================
  531. ;* Edge scan conversion DDA moving down and to the right.
  532. ;* eax = xpos, ebx = span to reference
  533. ;*==================================================================
  534. ??r_scan:
  535. cmp ebx,[span_buff]
  536. jg ??r_scan_convert
  537. ??r_scan_convert_loop:
  538. cmp [DWORD PTR ebx],SLOT_VACANT ; if the left slot of span is
  539. jne short ??r_next_slot ; vacant fill it with xpos
  540. mov [ebx],ax
  541. ??r_next_slot:
  542. mov [ebx + 2],ax ; otherwise fill the right slot
  543. ; with xpos
  544. ??r_scan_convert:
  545. dec ecx
  546. jl short ??exit
  547. add ebx,4
  548. add eax,edi
  549. add edx,esi
  550. jle short ??r_scan_convert_loop
  551. inc eax
  552. sub edx,[realignment]
  553. jmp ??r_scan_convert_loop
  554. ;*==================================================================
  555. ;* Scan convert a vertical edge.
  556. ;* eax = xpos, ebx = span to reference
  557. ;*==================================================================
  558. ??v_scan:
  559. cmp ebx,[span_buff]
  560. jg ??v_scan_convert
  561. ??v_scan_convert_loop:
  562. cmp [DWORD PTR ebx],SLOT_VACANT ; if the left slot of span is
  563. jne short ??v_next_slot ; vacant fill it with xpos
  564. mov [ebx],ax
  565. ??v_next_slot:
  566. mov [ebx + 2],ax ; otherwise fill the right slot
  567. ; with xpos
  568. ??v_scan_convert:
  569. add ebx,4
  570. dec edx
  571. jge ??v_scan_convert_loop
  572. ??exit:
  573. retn
  574. ENDP Buffer_Fill_Quad
  575. END