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.

905 lines
32 KiB

  1. ;---------------------------Module-Header------------------------------;
  2. ; Module Name: str.asm
  3. ;
  4. ; Contains the x86 'Asm' versions of some inner-loop routines for the
  5. ; partially hardware accelerated StretchBlt.
  6. ;
  7. ; Copyright (c) 1994-1995 Microsoft Corporation
  8. ;-----------------------------------------------------------------------;
  9. .386
  10. .model small,c
  11. assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
  12. assume fs:nothing,gs:nothing
  13. .xlist
  14. include stdcall.inc ;calling convention cmacros
  15. include i386\strucs.inc
  16. include i386\hw.inc
  17. .list
  18. .data
  19. ;
  20. ; stack based params and local variables
  21. ;
  22. STACK_STRUC struc
  23. ; Feel free to add any local variables here:
  24. sp_TempXFrac dd ?
  25. sp_YCarry dd ?
  26. sp_LeftCase dd ?
  27. sp_RightCase dd ?
  28. sp_pjSrcScan dd ?
  29. sp_SrcIntStep dd ?
  30. sp_DstStride dd ?
  31. sp_XCntHW dd ?
  32. sp_XCount dd ?
  33. sp_xyOFfset dd ?
  34. sp_yDst dd ?
  35. sp_pdev dd ?
  36. ; Don't add any fields below here without modifying PROC_MEM_SIZE!
  37. sp_ebp dd ?
  38. sp_esi dd ?
  39. sp_edi dd ?
  40. sp_ebx dd ?
  41. sp_RetAddr dd ?
  42. sp_pSTR_BLT dd ? ; If adding parameters, adjust 'ret' value!
  43. STACK_STRUC ends
  44. PROC_MEM_SIZE equ 6 * 4
  45. ;
  46. ; Make sure this STR_BLT matches that declared in driver.h!
  47. ;
  48. STR_BLT struc
  49. str_ppdev dd ?
  50. str_pjSrcScan dd ?
  51. str_lDeltaSrc dd ?
  52. str_XSrcStart dd ?
  53. str_pjDstScan dd ?
  54. str_lDeltaDst dd ?
  55. str_XDstStart dd ?
  56. str_XDstEnd dd ?
  57. str_YDstStart dd ?
  58. str_YDstCount dd ?
  59. str_ulXDstToSrcIntCeil dd ?
  60. str_ulXDstToSrcFracCeil dd ?
  61. str_ulYDstToSrcIntCeil dd ?
  62. str_ulYDstToSrcFracCeil dd ?
  63. str_ulXFracAccumulator dd ?
  64. str_ulYFracAccumulator dd ?
  65. STR_BLT ends
  66. .code
  67. ;---------------------------Public-Routine------------------------------;
  68. ; VOID vDirectStretch8(pStrBlt)
  69. ;
  70. ; NOTE: This routine doesn't handle cases where the blt stretch starts
  71. ; and ends in the same destination dword! vDirectStretchNarrow
  72. ; is expected to have been called for that case.
  73. ;
  74. ; Stretch blt 8 -> 8
  75. ;-----------------------------------------------------------------------;
  76. public vDirectStretch8@4
  77. vDirectStretch8@4 proc near
  78. ;
  79. ; use ebp as general register, use esp for parameter and local access
  80. ; save ebp,ebx,esi,edi
  81. ;
  82. push ebx
  83. push edi
  84. push esi
  85. push ebp
  86. sub esp,(size STACK_STRUC) - PROC_MEM_SIZE ; make room for local variables
  87. mov ebp,[esp].sp_pSTR_BLT ; load pSTR_BLT into ebp
  88. ;
  89. ; load up some stack-based parameters to be used by our scan
  90. ; duplicator when doing vertical stretches
  91. ;
  92. mov eax,[ebp].str_ppdev
  93. mov ecx,[ebp].str_YDstStart ; get start y coordinate
  94. mov [esp].sp_pdev,eax ; save ppdev pointer
  95. mov ebx,[eax].pdev_xyOffset
  96. mov [esp].sp_xyOffset,ebx ; save xyOffset
  97. mov [esp].sp_yDst,ecx ; save current y coordinate
  98. ;
  99. ; calc starting addressing parameters
  100. ;
  101. mov esi,[ebp].str_pjSrcScan ; load src DIB pointer
  102. add esi,[ebp].str_XSrcStart ; add starting Src Pixel
  103. mov edi,[ebp].str_pjDstScan ; load dst DIB pointer
  104. add edi,[ebp].str_XDstStart ; add strarting Dst Pixel
  105. mov [esp].sp_pjSrcScan,esi ; save scan line start pointer
  106. mov eax,[ebp].str_ulYDstToSrcIntCeil ; number of src scan lines to step
  107. mul [ebp].str_lDeltaSrc ; calc scan line int lines to step
  108. mov [esp].sp_SrcIntStep,eax ; save int portion of Y src step
  109. mov edx,4 ; calc left bytes = (4 - LeftCase) & 0x03
  110. sub edx,edi
  111. and edx,3 ; left edge bytes
  112. mov [esp].sp_LeftCase,edx ; save left edge case pixels (4-LeftCase)&0x03
  113. mov eax,[ebp].str_pjDstScan ; make copy
  114. mov ecx,[ebp].str_XDstEnd ; load x end
  115. add eax,ecx ; ending dst addr
  116. and eax,3 ; calc right edge case
  117. mov [esp].sp_RightCase,eax ; save right edge case
  118. sub ecx,[ebp].str_XDstStart ; calc x count
  119. dec ecx
  120. mov [esp].sp_XCntHW,ecx ; x width for accelerator
  121. inc ecx
  122. mov ebx,[ebp].str_lDeltaDst ; dst scan line stride
  123. sub ebx,ecx ; distance from end of one line to start of next
  124. mov [esp].sp_DstStride,ebx ; save dst scan line stride
  125. sub ecx,eax ; sub right edge from XCount
  126. sub ecx,edx ; sub left edge from XCount
  127. shr ecx,2 ; convert from byte to DWORD count
  128. mov [esp].sp_XCount,ecx ; save DWORD count
  129. mov ebx,[ebp].str_ulXDstToSrcFracCeil ; get x frac
  130. mov [esp].sp_TempXFrac,ebx ; save x frac to a esp based location
  131. NextScan:
  132. ;
  133. ; Wait until the accelerator is done with current blt
  134. ;
  135. mov dx,3ceh ;index register
  136. mov al,31h ;status reg
  137. out dx,al
  138. mov dx,3cfh ;data register
  139. @@: in al,dx
  140. test al,1
  141. jnz short @b
  142. SingleLoop:
  143. ;
  144. ; esi and edi are assumed to be correctly loaded
  145. ;
  146. mov eax,[ebp].str_ulXDstToSrcIntCeil ; get src integer step for step in dst
  147. mov ebx,[ebp].str_ulXDstToSrcFracCeil ; get src frac step for step in dst
  148. mov edx,[ebp].str_ulXFracAccumulator ; put it in edx as tmp
  149. mov ebp,edi ; get dst pointer to ebp
  150. ;
  151. ; Can't directly access pSTR_BLT variables through ebp
  152. ;
  153. mov edi,edx ; get accumulator where we want it
  154. mov ecx,[esp].sp_LeftCase
  155. ; eax = integer step in source
  156. ; ebx = fractional step in source
  157. ; ecx = left edge case
  158. ; edx = free for pixel data
  159. ; esi = pointer to source pixel
  160. ; edi = fractional accumulator
  161. ; ebp = pointer to dest pixel
  162. ;
  163. ; first do the left side to align dwords
  164. ;
  165. test ecx,ecx
  166. jz DwordAligned
  167. @@:
  168. mov dl,[esi] ; fetch pixel
  169. mov [ebp],dl ; write it out
  170. add edi,ebx ; step fraction
  171. adc esi,eax ; add in integer and possible carry
  172. inc ebp ; step 1 in dest
  173. dec ecx ; dec left count
  174. jne @B ; repeat until done
  175. DwordAligned:
  176. mov ecx,[esp].sp_XCount ; get run length
  177. @@:
  178. mov dl,[esi] ; get a source pixel edx = ???0
  179. add edi,ebx ; step fraction
  180. adc esi,eax ; add integer and carry
  181. add edi,ebx ; step fraction
  182. mov dh,[esi] ; get source pixel edx = ??10
  183. adc esi,eax ; add integer and carry
  184. shl edx,16 ; edx = 10??
  185. add edi,ebx ; step fraction
  186. mov dl,[esi] ; get a source pixel edx = 10?2
  187. adc esi,eax ; add integer and carry
  188. add edi,ebx ; step fraction
  189. mov dh,[esi] ; get source pixel edx = 0132
  190. adc esi,eax ; add integer and carry
  191. ror edx,16 ; edx = 3210
  192. mov [ebp],edx ; write everything to dest
  193. add ebp,4 ; increment dest pointer by 1 dword
  194. dec ecx ; decrement count
  195. jnz @b ; do more pixels
  196. ;
  197. ; now do the right side trailing bytes
  198. ;
  199. mov ecx,[esp].sp_RightCase
  200. test ecx,ecx
  201. jz EndScanLine
  202. @@:
  203. mov dl,[esi] ; fetch pixel
  204. mov [ebp],dl ; write it out
  205. add edi,ebx ; step fraction
  206. adc esi,eax ; add in integer and possible carry
  207. inc ebp ; step 1 in dest
  208. dec ecx ; dec right count
  209. jnz @b ; repeat until done
  210. EndScanLine:
  211. mov edi,ebp ; get dst pointer back
  212. mov ebp,[esp].sp_pSTR_BLT ; load pSTR_BLT into ebp
  213. EndSkipScan:
  214. mov esi,[esp].sp_pjSrcScan ; load src scan start addr
  215. mov ebx,esi ; save a copy
  216. mov eax,[ebp].str_ulYFracAccumulator ; get .32 part of Y pointer
  217. add eax,[ebp].str_ulYDstToSrcFracCeil ; add in fractional step
  218. jnc @f
  219. add esi,[ebp].str_lDeltaSrc ; step one extra in src
  220. @@: mov [ebp].str_ulYFracAccumulator,eax ; save Y accumulator
  221. add esi,[esp].sp_SrcIntStep ; step int part
  222. mov [esp].sp_pjSrcScan,esi ; save starting scan addr
  223. add edi,[esp].sp_DstStride ; step to next scan in dst
  224. dec [ebp].str_YDstCount ; decrement scan count
  225. jz Done ; no more scans
  226. inc [esp].sp_yDst ; one scan further down in dst
  227. cmp esi,ebx ; is src scan same as before?
  228. jne NextScan ; if so, fall through to dupe scan
  229. ;--------------------------------------------------------------------
  230. ; The source scan is the same one used for the previous destination
  231. ; scan, so we can simply use the hardware to copy the previous
  232. ; destination scan.
  233. ;
  234. ; Since on the S3 we can set up a 'rolling blt' to copy one scan
  235. ; line to several scans in a single command, we will count up how
  236. ; many times this scan should be duplicated. If your hardware
  237. ; cannot do a rolling blt, simply issue a new blt command for
  238. ; every time the scan should be duplicated.
  239. ;
  240. ; eax = ulYFracAccumulator
  241. ; ebx = original pjSrcScan
  242. ; esi = current pjSrcScan
  243. ; ebp = pSTR_BLT
  244. ;
  245. mov ecx,-1 ; number of times scan is to be
  246. ; duplicated, less one
  247. AnotherDuplicate:
  248. inc ecx ; one scan further down
  249. dec [ebp].str_YDstCount ; decrement scan count
  250. jz OutputDuplicates ; no more scans
  251. add eax,[ebp].str_ulYDstToSrcFracCeil ; add in fractional step
  252. jnc @f
  253. add esi,[ebp].str_lDeltaSrc ; step one extra in src
  254. @@: add esi,[esp].sp_SrcIntStep ; step int part
  255. add edi,[ebp].str_lDeltaDst ; step entire dest scan
  256. cmp esi,ebx ; is src scan same as before?
  257. je AnotherDuplicate
  258. OutputDuplicates:
  259. mov [esp].sp_pjSrcScan,esi ; save starting scan address
  260. mov [ebp].str_ulYFracAccumulator,eax ; save Y accumulator
  261. ;
  262. ; Now output the command to do the 'rolling blt'
  263. ;
  264. ;; mov edx,[esp].sp_pjBase
  265. ;
  266. ; Wait until the accelerator is done with current blt
  267. ;
  268. mov dx,3ceh ;index register
  269. mov al,31h ;status reg
  270. out dx,al
  271. mov dx,3cfh ;data register
  272. @@: in al,dx
  273. test al,1
  274. jnz short @b
  275. mov ebx,[esp].sp_XCntHW
  276. mov eax,[esp].sp_yDst
  277. ; eax = yDst -- Destination scan line (source scan line is yDst - 1)
  278. ; ebx = XCntHW -- Number of bytes across (width) - 1
  279. ; ecx = cy -- Number of times scan is to be duplicated - 1
  280. ; ebp = pSTR_BLT -- Stretch blt info
  281. DuplicateViaMmIo:
  282. ;
  283. ; Do the copy:
  284. ;
  285. if 0
  286. CP_XCNT(ppdev, pjBase, (WidthXBytes - 1));
  287. CP_YCNT(ppdev, pjBase, (cyDuplicate - 1));
  288. CP_SRC_ADDR(ppdev, pjBase, (xyOffset + ((yDst - 1) * lDelta) + xDstBytes));
  289. SET_DEST_ADDR(ppdev, ((yDst * lDelta) + xDstBytes));
  290. START_ACL(ppdev);
  291. endif
  292. .errnz RECT_HEIGHT
  293. ;; mov [edx+OFFSET_wXCnt],bx
  294. ;; mov [edx+OFFSET_wYCnt],cx
  295. mov dx,3ceh ;index register
  296. ;
  297. ; set XCNT=bx and YCNT=cx
  298. ;
  299. push eax
  300. mov al,21h ;BLT_WIDTH_HIGH
  301. mov ah,bh ;x count high byte
  302. out dx,ax
  303. mov al,20h ;BLT_WIDTH_LOW
  304. mov ah,bl ;x count low byte
  305. out dx,ax
  306. mov al,23h ;BLT_HEIGHT_HIGH
  307. mov ah,ch ;y count high byte
  308. out dx,ax
  309. mov al,22h ;BLT_HEIGHT_LOW
  310. mov ah,cl ;y count low byte
  311. out dx,ax
  312. pop eax
  313. ;
  314. ; Calculate src address
  315. ;
  316. mov ebx,eax ; ebx <- yDst
  317. dec ebx
  318. imul ebx,[ebp].str_lDeltaDst
  319. add ebx,[esp].sp_xyOffset
  320. add ebx,[ebp].str_xDstStart
  321. ;; mov [edx+OFFSET_ulSrcAddr],ebx
  322. push eax
  323. mov al,2ch ;SRC_ADDR_LOW
  324. mov ah,bl ;src addr low byte
  325. out dx,ax
  326. mov al,2dh ;SRC_ADDR_MID
  327. mov ah,bh ;src addr mid byte
  328. out dx,ax
  329. shr ebx,16
  330. mov al,2eh ;SRC_ADDR_HIGH
  331. mov ah,bl ;src addr high byte
  332. out dx,ax
  333. pop eax
  334. ;
  335. ; Calculate dst address
  336. ;
  337. inc eax ; account for 'ecx' being
  338. ; one less than scan count
  339. mov ebx,eax ; ebx <- yDst
  340. dec ebx
  341. imul ebx,[ebp].str_lDeltaDst
  342. add ebx,[esp].sp_xyOffset
  343. add ebx,[ebp].str_xDstStart
  344. ;; mov [edx+OFFSET_ulDstAddr],ebx
  345. push eax
  346. mov al,28h ;DST_ADDR_LOW
  347. mov ah,bl ;dst addr low byte
  348. out dx,ax
  349. mov al,29h ;DST_ADDR_MID
  350. mov ah,bh ;dst addr mid byte
  351. out dx,ax
  352. shr ebx,16
  353. mov al,2ah ;DST_ADDR_HIGH
  354. mov ah,bl ;dst addr high byte
  355. out dx,ax
  356. ;
  357. ; Start blt
  358. ;
  359. mov al,31h ;BLT_START_STATUS_REG
  360. mov ah,2 ;BLT_START
  361. out dx,ax
  362. pop eax
  363. DoneSetDestAddr:
  364. add eax,ecx ; add num scans just done
  365. mov [esp].sp_yDst,eax
  366. DoneDuplicate:
  367. cmp [ebp].str_YDstCount,0 ; we might be all done
  368. jne NextScan
  369. Done:
  370. add esp,(size STACK_STRUC) - PROC_MEM_SIZE
  371. pop ebp
  372. pop esi
  373. pop edi
  374. pop ebx
  375. ret 4
  376. vDirectStretch8@4 endp
  377. ;---------------------------Public-Routine------------------------------;
  378. ; VOID vDirectStretch16(pStrBlt)
  379. ;
  380. ; Stretch blt 16 -> 16
  381. ;-----------------------------------------------------------------------;
  382. public vDirectStretch16@4
  383. vDirectStretch16@4 proc near
  384. ;
  385. ; use ebp as general register, use esp for parameter and local access
  386. ; save ebp,ebx,esi,edi
  387. ;
  388. push ebx
  389. push edi
  390. push esi
  391. push ebp
  392. sub esp,(size STACK_STRUC) - PROC_MEM_SIZE ; make room for local variables
  393. mov ebp,[esp].sp_pSTR_BLT ; load pSTR_BLT into ebp
  394. ;
  395. ; load up some stack-based parameters to be used by our scan
  396. ; duplicator when doing vertical stretches
  397. ;
  398. mov eax,[ebp].str_ppdev
  399. mov ecx,[ebp].str_YDstStart ; get start y coordinate
  400. mov [esp].sp_pdev,eax ; save ppdev pointer
  401. mov ebx,[eax].pdev_xyOffset
  402. mov [esp].sp_xyOffset,ebx ; save xyOffset
  403. mov [esp].sp_yDst,ecx ; save current y coordinate
  404. ;
  405. ; calc starting addressing parameters
  406. ;
  407. mov esi,[ebp].str_pjSrcScan ; load src DIB pointer
  408. mov eax,[ebp].str_XSrcStart
  409. mov edi,[ebp].str_pjDstScan ; load dst DIB pointer
  410. mov ebx,[ebp].str_XDstStart
  411. add esi,eax
  412. add edi,ebx
  413. add esi,eax ; add starting Src Pixel
  414. add edi,ebx ; add starting Dst Pixel
  415. mov [esp].sp_pjSrcScan,esi ; save scan line start pointer
  416. mov eax,[ebp].str_ulYDstToSrcIntCeil ; number of src scan lines to step
  417. mul [ebp].str_lDeltaSrc ; calc scan line int lines to step
  418. mov [esp].sp_SrcIntStep,eax ; save int portion of Y src step
  419. mov edx,edi ; make copy of pjDst
  420. and edx,2 ; calc left edge case
  421. shr edx,1 ; left edge pixels
  422. mov [esp].sp_LeftCase,edx ; save left edge case pixels
  423. mov eax,[ebp].str_pjDstScan ; make copy
  424. mov ecx,[ebp].str_XDstEnd ; load x end
  425. add eax,ecx
  426. add eax,ecx ; ending dst addr
  427. and eax,2 ; calc right edge case
  428. shr eax,1 ; right edge pixels
  429. mov [esp].sp_RightCase,eax ; save right edge case
  430. sub ecx,[ebp].str_XDstStart ; calc x count
  431. shl ecx,1
  432. dec ecx
  433. mov [esp].sp_XCntHW,ecx ; x width for accelerator
  434. inc ecx
  435. shr ecx,1
  436. mov ebx,[ebp].str_lDeltaDst ; dst scan line stride
  437. sub ebx,ecx
  438. sub ebx,ecx ; distance from end of one line to start of next
  439. mov [esp].sp_DstStride,ebx ; save dst scan line stride
  440. sub ecx,eax ; sub right edge from XCount
  441. sub ecx,edx ; sub left edge from XCount
  442. shr ecx,1 ; convert from pixels to DWORD count
  443. mov [esp].sp_XCount,ecx ; save DWORD count
  444. mov ebx,[ebp].str_ulXDstToSrcFracCeil ; get x frac
  445. mov [esp].sp_TempXFrac,ebx ; save x frac to a esp based location
  446. NextScan:
  447. ;
  448. ; Wait until the accelerator is done with current blt
  449. ;
  450. mov dx,3ceh ;index register
  451. mov al,31h ;status reg
  452. out dx,al
  453. mov dx,3cfh ;data register
  454. @@: in al,dx
  455. test al,1
  456. jnz short @b
  457. SingleLoop:
  458. ;
  459. ; esi and edi are assumed to be correctly loaded
  460. ;
  461. mov eax,[ebp].str_ulXDstToSrcIntCeil ; get src integer step for step in dst
  462. mov ebx,[ebp].str_ulXDstToSrcFracCeil ; get src frac step for step in dst
  463. mov edx,[ebp].str_ulXFracAccumulator ; put it in edx as tmp
  464. mov ebp,edi ; get dst pointer to ebp
  465. ;
  466. ; Can't directly access pSTR_BLT variables through ebp
  467. ;
  468. mov edi,edx ; get accumulator where we want it
  469. mov ecx,[esp].sp_LeftCase
  470. ; eax = integer step in source
  471. ; ebx = fractional step in source
  472. ; ecx = left edge case
  473. ; edx = free for pixel data
  474. ; esi = pointer to source pixel
  475. ; edi = fractional accumulator
  476. ; ebp = pointer to dest pixel
  477. ;
  478. ; divide 'esi' by 2 so that we can always dereference it by
  479. ; [2*esi] -- this allows us to still use an 'add with carry'
  480. ; to jump to the next pixel
  481. ;
  482. shr esi,1
  483. ;
  484. ; first do the left side to align dwords
  485. ;
  486. test ecx,ecx
  487. jz DwordAligned
  488. mov dx,[2*esi] ; fetch pixel
  489. mov [ebp],dx ; write it out
  490. add edi,ebx ; step fraction
  491. adc esi,eax ; add in integer and possible carry
  492. add ebp,2 ; step 1 in dest
  493. DwordAligned:
  494. mov ecx,[esp].sp_XCount ; get run length
  495. test ecx,ecx
  496. jz TrailingBytes ; watch for zero dword case
  497. @@:
  498. mov dx,[2*esi] ; get a source pixel
  499. add edi,ebx ; step fraction
  500. adc esi,eax ; add integer and carry
  501. shl edx,16
  502. add edi,ebx ; step fraction
  503. mov dx,[2*esi] ; get source pixel
  504. adc esi,eax ; add integer and carry
  505. ror edx,16
  506. mov [ebp],edx ; write everything to dest
  507. add ebp,4 ; increment dest pointer by 1 dword
  508. dec ecx ; decrement count
  509. jnz @b ; do more pixels
  510. TrailingBytes:
  511. ;
  512. ; now do the right side trailing bytes
  513. ;
  514. mov ecx,[esp].sp_RightCase
  515. test ecx,ecx
  516. jz EndScanLine
  517. mov dx,[2*esi] ; fetch pixel
  518. mov [ebp],dx ; write it out
  519. add edi,ebx ; step fraction
  520. adc esi,eax ; add in integer and possible carry
  521. add ebp,2 ; step 1 in dest
  522. EndScanLine:
  523. mov edi,ebp ; get dst pointer back
  524. mov ebp,[esp].sp_pSTR_BLT ; load pSTR_BLT into ebp
  525. EndSkipScan:
  526. mov esi,[esp].sp_pjSrcScan ; load src scan start addr
  527. mov ebx,esi ; save a copy
  528. mov eax,[ebp].str_ulYFracAccumulator ; get .32 part of Y pointer
  529. add eax,[ebp].str_ulYDstToSrcFracCeil ; add in fractional step
  530. jnc @f
  531. add esi,[ebp].str_lDeltaSrc ; step one extra in src
  532. @@: mov [ebp].str_ulYFracAccumulator,eax ; save Y accumulator
  533. add esi,[esp].sp_SrcIntStep ; step int part
  534. mov [esp].sp_pjSrcScan,esi ; save starting scan addr
  535. add edi,[esp].sp_DstStride ; step to next scan in dst
  536. dec [ebp].str_YDstCount ; decrement scan count
  537. jz Done ; no more scans
  538. inc [esp].sp_yDst ; one scan further down in dst
  539. cmp esi,ebx ; is src scan same as before?
  540. jne NextScan ; if so, fall through to dupe scan
  541. ;--------------------------------------------------------------------
  542. ; The source scan is the same one used for the previous destination
  543. ; scan, so we can simply use the hardware to copy the previous
  544. ; destination scan.
  545. ;
  546. ; Since on the S3 we can set up a 'rolling blt' to copy one scan
  547. ; line to several scans in a single command, we will count up how
  548. ; many times this scan should be duplicated. If your hardware
  549. ; cannot do a rolling blt, simply issue a new blt command for
  550. ; every time the scan should be duplicated.
  551. ;
  552. ; eax = ulYFracAccumulator
  553. ; ebx = original pjSrcScan
  554. ; esi = current pjSrcScan
  555. ; ebp = pSTR_BLT
  556. ;
  557. mov ecx,-1 ; number of times scan is to be
  558. ; duplicated, less one
  559. AnotherDuplicate:
  560. inc ecx ; one scan further down
  561. dec [ebp].str_YDstCount ; decrement scan count
  562. jz OutputDuplicates ; no more scans
  563. add eax,[ebp].str_ulYDstToSrcFracCeil ; add in fractional step
  564. jnc @f
  565. add esi,[ebp].str_lDeltaSrc ; step one extra in src
  566. @@: add esi,[esp].sp_SrcIntStep ; step int part
  567. add edi,[ebp].str_lDeltaDst ; step entire dest scan
  568. cmp esi,ebx ; is src scan same as before?
  569. je AnotherDuplicate
  570. OutputDuplicates:
  571. mov [esp].sp_pjSrcScan,esi ; save starting scan address
  572. mov [ebp].str_ulYFracAccumulator,eax ; save Y accumulator
  573. ;
  574. ; Now output the command to do the 'rolling blt'
  575. ;
  576. ;; mov edx,[esp].sp_pjBase
  577. ;
  578. ; Wait until the accelerator is done with current blt
  579. ;
  580. mov dx,3ceh ;index register
  581. mov al,31h ;status reg
  582. out dx,al
  583. mov dx,3cfh ;data register
  584. @@: in al,dx
  585. test al,1
  586. jnz short @b
  587. mov ebx,[esp].sp_XCntHW
  588. mov eax,[esp].sp_yDst
  589. ; eax = yDst -- Destination scan line (source scan line is yDst - 1)
  590. ; ebx = XCntHW -- Number of bytes across (width) - 1
  591. ; ecx = cy -- Number of times scan is to be duplicated - 1
  592. ; edx = pjBase -- Pointer to memory mapped accelerator registers
  593. ; ebp = pSTR_BLT -- Stretch blt info
  594. DuplicateViaMmIo:
  595. ;
  596. ; Do the copy:
  597. ;
  598. if 0
  599. CP_XCNT(ppdev, pjBase, (WidthXBytes - 1));
  600. CP_YCNT(ppdev, pjBase, (cyDuplicate - 1));
  601. CP_SRC_ADDR(ppdev, pjBase, (xyOffset + ((yDst - 1) * lDelta) + xDstBytes));
  602. SET_DEST_ADDR(ppdev, ((yDst * lDelta) + xDstBytes));
  603. START_ACL(ppdev);
  604. endif
  605. .errnz RECT_HEIGHT
  606. ;; mov [edx+OFFSET_wXCnt],bx
  607. ;; mov [edx+OFFSET_wYCnt],cx
  608. mov dx,3ceh ;index register
  609. ;
  610. ; set XCNT=bx and YCNT=cx
  611. ;
  612. push eax
  613. mov al,21h ;BLT_WIDTH_HIGH
  614. mov ah,bh ;x count high byte
  615. out dx,ax
  616. mov al,20h ;BLT_WIDTH_LOW
  617. mov ah,bl ;x count low byte
  618. out dx,ax
  619. mov al,23h ;BLT_HEIGHT_HIGH
  620. mov ah,ch ;y count high byte
  621. out dx,ax
  622. mov al,22h ;BLT_HEIGHT_LOW
  623. mov ah,cl ;y count low byte
  624. out dx,ax
  625. pop eax
  626. ;
  627. ; Calculate src address
  628. ;
  629. mov ebx,eax ; ebx <- yDst
  630. dec ebx
  631. imul ebx,[ebp].str_lDeltaDst
  632. add ebx,[esp].sp_xyOffset
  633. add ebx,[ebp].str_xDstStart
  634. add ebx,[ebp].str_xDstStart
  635. ;; mov [edx+OFFSET_ulSrcAddr],ebx
  636. push eax
  637. mov al,2ch ;SRC_ADDR_LOW
  638. mov ah,bl ;src addr low byte
  639. out dx,ax
  640. mov al,2dh ;SRC_ADDR_MID
  641. mov ah,bh ;src addr mid byte
  642. out dx,ax
  643. shr ebx,16
  644. mov al,2eh ;SRC_ADDR_HIGH
  645. mov ah,bl ;src addr high byte
  646. out dx,ax
  647. pop eax
  648. ;
  649. ; Calculate dst address
  650. ;
  651. inc eax ; account for 'ecx' being
  652. ; one less than scan count
  653. mov ebx,eax ; ebx <- yDst
  654. dec ebx
  655. imul ebx,[ebp].str_lDeltaDst
  656. add ebx,[esp].sp_xyOffset
  657. add ebx,[ebp].str_xDstStart
  658. add ebx,[ebp].str_xDstStart
  659. ;; mov [edx+OFFSET_ulDstAddr],ebx
  660. push eax
  661. mov al,28h ;DST_ADDR_LOW
  662. mov ah,bl ;dst addr low byte
  663. out dx,ax
  664. mov al,29h ;DST_ADDR_MID
  665. mov ah,bh ;dst addr mid byte
  666. out dx,ax
  667. shr ebx,16
  668. mov al,2ah ;DST_ADDR_HIGH
  669. mov ah,bl ;dst addr high byte
  670. out dx,ax
  671. ;
  672. ; Start blt
  673. ;
  674. mov al,31h ;BLT_START_STATUS_REG
  675. mov ah,2 ;BLT_START
  676. out dx,ax
  677. pop eax
  678. DoneSetDestAddr:
  679. add eax,ecx ; add num scans just done
  680. mov [esp].sp_yDst,eax
  681. DoneDuplicate:
  682. cmp [ebp].str_YDstCount,0 ; we might be all done
  683. jne NextScan
  684. Done:
  685. add esp,(size STACK_STRUC) - PROC_MEM_SIZE
  686. pop ebp
  687. pop esi
  688. pop edi
  689. pop ebx
  690. ret 4
  691. vDirectStretch16@4 endp
  692. end