|
|
1.1 root 1: ;---------------------------Module-Header------------------------------;
2: ; Module Name: stretch.asm
3: ;
4: ; Copyright (c) 1992 Microsoft Corporation
5: ;-----------------------------------------------------------------------;
6: ;-----------------------------------------------------------------------;
7: ; INT vStretchBlt8bpp(PPDEV ppdev, PBYTE pSrc, LONG lSrcNext,
8: ; PRECTL prclSrc, PRECTL prclDest, PRECTL prclDestClip,
9: ; PULONG pulXlatVector)
10: ; Input:
11: ;
12: ; Performs accelerated stretch blts from 8-bit DIBs to 256-color VGA
13: ; display memory.
14: ;-----------------------------------------------------------------------;
15: ; Note: Does not handle source clipping.
16: ;
17: ; Note: Does not yet handle expansion, only shrinking.
18: ;-----------------------------------------------------------------------;
19:
20: comment $
21:
22: ***
23:
24: Note: in the noxlat loop, EBX isn't altered, so it could be used for
25: something else, like the scan line count. This isn't done currently
26: because the scan-line loop is shared by the xlat and noxlat cases, and
27: the xlat cases do alter EBX; separate loops would be needed in order
28: to perform this optimization.
29:
30: commend $
31:
32: ;-----------------------------------------------------------------------;
33:
34: .386
35:
36: ifndef DOS_PLATFORM
37: .model small,c
38: else
39: ifdef STD_CALL
40: .model small,c
41: else
42: .model small,pascal
43: endif; STD_CALL
44: endif; DOS_PLATFORM
45:
46: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
47: assume fs:nothing,gs:nothing
48:
49: .xlist
50: include stdcall.inc ;calling convention cmacros
51: include i386\strucs.inc
52: include i386\driver.inc
53:
54: .list
55:
56: ;-----------------------------------------------------------------------;
57:
58: .data
59:
60: ;-----------------------------------------------------------------------;
61:
62: .code
63:
64: ;-----------------------------------------------------------------------;
65:
66: cProc vStretchBlt8bpp,28,< \
67: uses esi edi ebx, \
68: ppdev:ptr, \
69: pSrc:ptr, \
70: lSrcNext:dword, \
71: prclSrc:ptr, \
72: prclDest:ptr, \
73: prclDestClip:ptr, \
74: pulXlatVector:dword >
75:
76: local pulDDAArray:dword ;pointer to array of n and n+1
77: ; values generated by DDA, used to
78: ; advance across source
79: local ulXStretchCount:dword ;# of pixels or pixel pair to copy to
80: ; (pixel pairs except in narrow
81: ; cases; doesn't include leading or
82: ; trailing single pixels in pixel
83: ; pair cases)
84: local ulDestNext:dword ;offset from last dest pixel on one
85: ; scan to first on next
86: local ulSrcMinNext:dword ;offset from start of one source scan
87: ; to start of next scan that's skipped
88: ; to by minimum DDA advance (basically,
89: ; skips over n scans when DDA advances
90: ; either n or n+1 scans)
91: local lYErrorTerm:dword ;current error term for the DDA in Y
92: local ulYAdjUp:dword ;error term adjust up for advancing
93: ; DDA in Y
94: local ulYAdjDown:dword ;error term adjust down for advancing
95: ; DDA in Y
96: local ulDstTopScan:dword ;top scan of dest text rect in
97: ; current bank
98: local ulDstBottomScan :dword ;bottom scan line of dest rectangle
99: local ulScanCount:dword ;# of scans to stretch in current
100: ; bank
101: local pfnRowVector:dword ;pointer to routine to be used to
102: ; stretch each row
103: local pfnStretchFn:dword ;pointer to routine to do a bank's
104: ; worth of stretching
105: local ulSrcTopScan:dword ;top scan line of source from which
106: ; to copy (after clipping, if needed)
107: local ulYMinStep:dword ;minimum # of scans to skip in source
108: ; when advancing dest one scan
109: local lXDstRight:dword ;right edge of dest area to which to
110: ; stretch, accounting for clipping
111: local lXDstLeft:dword ;left edge of dest area to which to
112: ; stretch, accounting for clipping
113: local ulXAdjUp:dword ;X error term adjust up
114: local ulXMinStep:dword ;X minimum step per dest 1-pixel step
115: local ulXAdjDown:dword ;X error term adjust down
116: local lXSrcRight:dword ;right edge of source area from which
117: ; to stretch, accounting for clipping
118: local lXSrcLeft:dword ;left edge of source area from which to
119: ; stretch, accounting for clipping
120:
121: ;-----------------------------------------------------------------------;
122:
123: mov esi,prclSrc
124: mov edi,prclDest
125:
126: mov eax,[esi].xRight
127: mov edx,[esi].xLeft
128: mov lXSrcLeft,edx
129: sub eax,edx ;EAX = source width
130: mov ecx,[edi].xRight
131: mov lXDstRight,ecx
132: mov edx,[edi].xLeft
133: mov lXDstLeft,edx
134: sub ecx,edx ;ECX = dest width
135:
136: cmp eax,ecx ;shrink or stretch in X?
137: jge short x_shrink ;shrink
138: ;stretch
139: ;@@@
140: DoneFailed:
141: sub eax,eax ;@@@shouldn't have to return a value
142: jmp done
143:
144: ;The destination is narrower than the source
145: x_shrink:
146: mov pfnStretchFn,offset shrink_8bpp_loop
147:
148: ;-----------------------------------------------------------------------;
149: ; Precalculate the DDA steps for X and store them in the temp buffer. We know
150: ; these will fit in the temp buffer, because there are only, say, 2K steps
151: ; max across the screen, and the temp buffer is guaranteed to be more than
152: ; 2K*4 = 8K bytes long.
153: ;
154: ; At this point, EAX = source width, ECX = destination width
155: ;-----------------------------------------------------------------------;
156:
157: sub edx,edx ;prepare for division
158: div ecx ;SourceDeltaX / DestDeltaX
159: mov ulXMinStep,eax ;EAX = minimum step in source for 1 dest step
160:
161: mov esi,edx ;set aside SourceDeltaX % DestDeltaX
162: add edx,edx ;scale up ulXAdjUp by 2 so we can handle a
163: ; half-pixel advance
164: mov ulXAdjUp,edx ;ulXAdjUp = (SourceDeltaX % DestDeltaX)*2
165:
166: ;prestep source X coord and error term by 1/2
167: ; a destination pixel, so we pick the source
168: ; pixel that most closely matches the center
169: ; of each destination pixel
170:
171: ;step by 1/2 the whole source pixel advance
172: ; per destination step
173: shr eax,1 ;minimum step/2
174: jnc short @F ;odd
175: ;even
176: add esi,ecx ;advance error term for 1/2 of the source
177: ; pixel we just split (by DestDeltaX)
178: @@:
179: add lXSrcLeft,eax ;advance 1/2 minimum step in source
180: add ecx,ecx ;scale up DestDeltaX by 2 so we can handle a
181: ; half-pixel advance
182: mov ulXAdjDown,ecx ;ulXAdjDown = DestDeltaX*2
183:
184: sub esi,ecx ;initial error term = -(DestDeltaX*2) + 1/2
185: ; normal error term step (for 1/2 pixel dest
186: ; advance effect on error term; note that 1/2
187: ; effect on whole source pixels has already
188: ; been accounted for)
189:
190: ;-----------------------------------------------------------------------;
191: ; Clip to the dest in X, if necessary.
192: ;-----------------------------------------------------------------------;
193:
194: mov ebx,prclDestClip
195: and ebx,ebx ;any clipping?
196: jz short x_clip_done ;no, all set
197: mov eax,[ebx].xRight ;right clip edge
198: cmp eax,lXDstRight ;is the right edge clipped?
199: jge short check_x_left_clip ;no
200: ;right edge is clipped
201: mov lXDstRight,eax ;set the clipped right edge
202: check_x_left_clip:
203: mov eax,[ebx].xLeft ;left clip edge
204: cmp eax,lXDstLeft ;is the left edge clipped?
205: jle short check_x_not_fully_clipped ;no
206: ;left edge is clipped
207: mov edx,lXDstLeft ;get the unclipped dest left edge
208: mov lXDstLeft,eax ;set the clipped dest left edge
209: ;now figure out how many source pixels
210: ; were clipped, and advance the error
211: ; term appropriately
212: sub eax,edx ;# of dest pixels clipped
213: mov ecx,eax ;set aside # of dest pixels to skip
214: mul ulXAdjUp ;# of adjust ups in the course of the
215: ; skipped pixels
216: add esi,eax ;EDX:ESI = error term after skipping
217: adc edx,-1 ;(the initial error term is negative;
218: ; this stretches it to 64 bits)
219: jnc short check_x_not_fully_clipped ;didn't turn over even once
220: mov eax,esi ;EDX:EAX = error term after skipping
221: div ulXAdjDown ;EAX = # of times to adjust down
222: ; while skipping pixels, minus 1
223: sub edx,ulXAdjDown ;do the last adjust down, to cross
224: ; back into negative territory where
225: ; the error term belongs
226: mov esi,edx ;error term at new, clipped dest left
227: ; edge
228: inc eax ;count the last adjust down (# of times
229: ; source error turned over while
230: ; advancing to the clipped left edge)
231: imul ecx,ulXMinStep ;# of whole pixels skipped in source
232: ; while advancing to dest clip left
233: ; edge
234: add eax,ecx ;total # of pixels skipped in source
235: ; while advancing to dest clip left
236: ; edge
237: add lXSrcLeft,eax ;advance the source left edge to match
238: ; advancing the destination left edge
239: ; to the left edge of the clip
240: ; rectangle
241: check_x_not_fully_clipped:
242: mov eax,lXDstLeft
243: cmp lXDstRight,eax ;is the destination fully x-clipped?
244: jle done ;yes, nothing to draw
245: x_clip_done:
246:
247: ;-----------------------------------------------------------------------;
248: ; Now actually generate the (possibly clipped) X DDA skip array
249: ;
250: ; At this point, ESI = X error term for left edge (accounting for any
251: ; X clipping that has occurred)
252: ;-----------------------------------------------------------------------;
253:
254: mov edx,ppdev
255: mov eax,ulXMinStep
256: mov edi,[edx].pdev_pvTmp ;we'll store the DDA steps in the temp
257: mov pulDDAArray,edi ; buffer
258:
259: mov edx,ulXAdjUp
260: mov ebx,ulXAdjDown
261: mov ecx,lXDstRight
262: sub ecx,lXDstLeft ;ECX = # of pixels per dest scan
263: push ecx ;remember # of dest pixels across
264: push ebp ;preserve stack frame pointer
265: lea ebp,[eax+1] ;maximum step
266: ;***stack frame unavailable***
267: x_shrink_set_dda_loop:
268: add esi,edx ;adjust the error term up
269: jnc short x_shrink_set_dda_min ;didn't turn over, so advance
270: ; minimum step
271: x_shrink_set_dda_max:
272: sub esi,ebx ;turned over; adjust error term back down
273: mov [edi],ebp ;advance by maximum step
274: add edi,4 ;point to next DDA array storage location
275: dec ecx ;count down steps
276: jz short x_shrink_set_dda_done ;no more steps
277: add esi,edx ;adjust the error term up
278: jc x_shrink_set_dda_max ;did turn over, so advance maximum step
279: x_shrink_set_dda_min:
280: mov [edi],eax ;advance by minimum step
281: add edi,4 ;point to next DDA array storage location
282: dec ecx ;count down steps
283: jnz x_shrink_set_dda_loop
284: x_shrink_set_dda_done:
285: mov dword ptr [edi],0 ;mark the end of the DDA
286: pop ebp ;restore stack frame pointer
287: ;***stack frame available***
288: pop ecx ;retrieve # of dest pixels across
289:
290: mov edi,prclDest
291: cmp pulXlatVector,0 ;translation?
292: jz short x_shrink_noxlat ;no
293: ;yes
294: cmp ecx,3 ;narrow case?
295: ja short @F ;no
296: mov pfnRowVector,offset shrink_xlat_8bpp_narrow ;narrow case
297: mov ulXStretchCount,ecx ;do all dest pixels one at a time
298: jmp check_y_shrink
299: @@: ;not narrow case; figure out which wide case,
300: ; based on the need to perform as many word-
301: ; aligned writes to display memory as possible
302: mov edx,ecx
303: test [edi].xLeft,1 ;starting at an odd destination address?
304: jnz short x_shrink_xlat_leading ;yes, need leading pixel
305: mov pfnRowVector,offset shrink_xlat_8bpp_nl_nt
306: ;assume no leading or trailing pixels
307: shr edx,1 ;destination width in pixel pairs
308: mov ulXStretchCount,edx ;count of pixel pairs to draw
309: jnc short check_y_shrink ;no leading or trailing pixels
310: mov pfnRowVector,offset shrink_xlat_8bpp_nl_t
311: ;no leading pixel, is a trailing pixel
312: jmp short check_y_shrink
313: x_shrink_xlat_leading: ;there is a leading pixel
314: mov pfnRowVector,offset shrink_xlat_8bpp_l_nt
315: ;assume no trailing pixel
316: shr edx,1 ;destination width in pixel pairs
317: mov ulXStretchCount,edx ;count of pixel pairs to draw
318: jc short check_y_shrink ;no trailing pixel
319: mov pfnRowVector,offset shrink_xlat_8bpp_l_t
320: ;both leading and trailing pixels
321: dec edx ;we'll do one pixel pair in the form
322: ; of the leading/trailing pixel pair
323: mov ulXStretchCount,edx ;count of pixel pairs to draw
324: jmp short check_y_shrink
325:
326: x_shrink_noxlat: ;no translation
327: cmp ecx,3 ;narrow case?
328: ja short @F ;no
329: mov pfnRowVector,offset shrink_noxlat_8bpp_narrow ;narrow case
330: mov ulXStretchCount,ecx ;do all dest pixels one at a time
331: jmp short check_y_shrink
332: @@: ;not narrow case; figure out which wide case,
333: ; based on the need to perform as many word-
334: ; aligned writes to display memory as possible
335: mov edx,ecx
336: test [edi].xLeft,1 ;starting at an odd destination address?
337: jnz short x_shrink_noxlat_leading ;yes, need leading pixel
338: mov pfnRowVector,offset shrink_noxlat_8bpp_nl_nt
339: ;assume no leading or trailing pixels
340: shr edx,1 ;destination width in pixel pairs
341: mov ulXStretchCount,edx ;count of pixel pairs to draw
342: jnc short check_y_shrink ;no leading or trailing pixels
343: mov pfnRowVector,offset shrink_noxlat_8bpp_nl_t
344: ;no leading pixel, is a trailing pixel
345: jmp short check_y_shrink
346: x_shrink_noxlat_leading: ;there is a leading pixel
347: mov pfnRowVector,offset shrink_noxlat_8bpp_l_nt
348: ;assume no trailing pixel
349: shr edx,1 ;destination width in pixel pairs
350: mov ulXStretchCount,edx ;count of pixel pairs to draw
351: jc short check_y_shrink ;no trailing pixel
352: mov pfnRowVector,offset shrink_noxlat_8bpp_l_t
353: ;both leading and trailing pixels
354: dec edx ;we'll do one pixel pair in the form
355: ; of the leading/trailing pixel pair
356: mov ulXStretchCount,edx ;count of pixel pairs to draw
357:
358: check_y_shrink:
359:
360: mov esi,edi ;ESI->prclDest
361: mov edi,prclSrc ;EDI->prclSrc
362: mov eax,[edi].yBottom
363: mov ecx,[edi].yTop
364: mov ulSrcTopScan,ecx
365: sub eax,ecx ;EAX = source height
366: mov ecx,[esi].yBottom
367: mov ulDstBottomScan,ecx
368: mov edx,[esi].yTop
369: mov ulDstTopScan,edx
370: sub ecx,edx ;ECX = dest height
371:
372: cmp eax,ecx ;shrink or stretch in Y?
373: jge short y_shrink ;shrink
374: ;stretch
375: ;@@@
376: sub eax,eax ;@@@shouldn't have to return a value
377: jmp done
378:
379: ;The destination is shorter than the source; calculate the error term values
380: ; for advancing through the source on a per-dest-scan-line basis.
381: y_shrink:
382: sub edx,edx ;prepare for division
383: div ecx ;SourceDeltaY/DestDeltaY
384: mov ulYMinStep,eax ;EAX = minimum step in source for 1 dest step
385:
386: mov ebx,edx ;set aside SourceDeltaY % DestDeltaY
387: add edx,edx ;scale up ulYAdjUp by 2 so we can handle a
388: ; half-pixel advance
389: mov ulYAdjUp,edx ;ulYAdjUp = (SourceDeltaY % DestDeltaY)*2
390:
391: imul lSrcNext ;(minimum step * source scan width in bytes)
392: mov ulSrcMinNext,eax ; = minimum offset by which to advance from
393: ; one scan to the next
394:
395: ;prestep source X coord and error term by 1/2
396: ; a destination pixel, so we pick the source
397: ; pixel that most closely matches the center
398: ; of each destination pixel
399:
400: ;step by 1/2 the whole source pixel advance
401: ; per destination step
402: mov eax,ulYMinStep ;retrieve minimum step
403: shr eax,1 ;minimum step/2
404: jnc short @F ;odd
405: ;even
406: add ebx,ecx ;advance error term for 1/2 of the source
407: ; pixel we just split
408: @@:
409: add ulSrcTopScan,eax ;advance 1/2 minimum step in source
410:
411: add ecx,ecx ;scale up DestDeltaY by 2 so we can handle a
412: ; half-pixel advance
413: mov ulYAdjDown,ecx ;ulYAdjDown = DestDeltaY*2
414:
415: sub ebx,ecx ;initial error term = -(DestDeltaY*2) + 1/2
416: ; normal error term step (for 1/2 pixel dest
417: ; advance effect on error term; note that 1/2
418: ; effect on whole source pixels has already
419: ; been accounted for)
420: mov lYErrorTerm,ebx
421:
422: ;-----------------------------------------------------------------------;
423: ; Clip in Y, if necessary.
424: ;-----------------------------------------------------------------------;
425:
426: mov ebx,prclDestClip
427: and ebx,ebx ;any clipping?
428: jz short y_clip_done ;no, all set
429: mov eax,[ebx].yBottom ;yes, clipping
430: ;see if the dest is clipped off the
431: ; bottom
432: cmp ulDstBottomScan,eax ;is the bottom clipped?
433: jle short check_y_top_clip ;no, check the top
434: mov ulDstBottomScan,eax ;yes, set the new bottom
435: check_y_top_clip:
436: ;see if the dest is clipped off the
437: ; top
438: mov eax,[ebx].yTop
439: cmp ulDstTopScan,eax ;is the top clipped?
440: jge short check_y_not_fully_clipped ;no
441: ;yes, so advance the top scan and the
442: ; error term accordingly
443: mov ulDstTopScan,eax ;top of clipped destination rectangle
444: sub eax,[esi].yTop ;# of destination scans to skip
445: mov ecx,eax ;set aside # of dest scans to skip
446: mul ulYAdjUp ;# of adjust ups in the course of the
447: ; skipped scans
448: add eax,lYErrorTerm ;EDX:EAX = error term after skipping
449: adc edx,-1 ;(the initial error term is negative;
450: ; this stretches it to 64 bits)
451: jnc short check_y_not_fully_clipped ;didn't turn over even once
452: div ulYAdjDown ;EAX = # of times to adjust down
453: ; while skipping scans, minus 1
454: sub edx,ulYAdjDown ;do the last adjust down, to cross
455: ; back into negative territory where
456: ; the error term belongs
457: mov lYErrorTerm,edx ;error term at new, clipped dest top
458: inc eax ;count the last adjust down (# of
459: ; times source error has turned over)
460: imul ecx,ulYMinStep ;# of whole steps in source while
461: ; advancing to dest clip top
462: add eax,ecx ;total # of scans skipped in source
463: ; while advancing to dest clip top
464: add ulSrcTopScan,eax ;advance the source top edge to match
465: ; advancing the destination top edge to
466: ; the top of the clip rectangle
467: check_y_not_fully_clipped:
468: mov eax,ulDstTopScan
469: cmp ulDstBottomScan,eax ;is the destination fully y-clipped?
470: jle done ;yes, nothing to draw
471: y_clip_done:
472:
473: ;-----------------------------------------------------------------------;
474: ; Calculate the offset of the initial destination pixel.
475: ;-----------------------------------------------------------------------;
476:
477: mov ebx,ppdev
478: mov eax,ulDstTopScan ;top scan line of text
479: mov esi,[ebx].pdev_lDeltaScreen
480: mul esi
481: mov edi,lXDstLeft
482: mov ecx,lXDstRight
483: sub ecx,edi ;dest width
484: sub esi,ecx ;dest width - width of a dest scan to stretch
485: mov ulDestNext,esi ;offset from end of one dest stretched
486: ; scan to start of next
487: add edi,eax
488:
489: ;-----------------------------------------------------------------------;
490: ; Map in the bank containing the top scan of the text, if it's not
491: ; mapped in already.
492: ;-----------------------------------------------------------------------;
493:
494: mov eax,ulDstTopScan ;top scan line of text
495: cmp eax,[ebx].pdev_rcl1WindowClip.yTop ;is text top less than
496: ; current bank?
497: jl short map_init_bank ;yes, map in proper bank
498: cmp eax,[ebx].pdev_rcl1WindowClip.yBottom ;text top greater than
499: ; current bank?
500: jl short init_bank_mapped ;no, proper bank already mapped
501: map_init_bank:
502:
503: ; Map in the bank containing the top scan line of the destination.
504: ; Preserves EBX, ESI, and EDI.
505:
506: ptrCall <dword ptr [ebx].pdev_pfnBankControl>,<ebx,eax,JustifyTop>
507:
508: init_bank_mapped:
509:
510: add edi,[ebx].pdev_pvBitmapStart ;initial destination address
511:
512: ;-----------------------------------------------------------------------;
513: ; Calculate the offset of the initial source pixel.
514: ;-----------------------------------------------------------------------;
515:
516: mov esi,prclSrc
517: mov eax,lSrcNext
518: imul ulSrcTopScan
519: mov esi,lXSrcLeft
520: add esi,eax
521: add esi,pSrc
522:
523: ;-----------------------------------------------------------------------;
524: ; Main loop for processing stretch blt in each bank.
525: ;
526: ; At start of loop, EBX->ppdev, ESI->current src, EDI->current dst
527: ;-----------------------------------------------------------------------;
528:
529: bank_loop:
530: mov edx,ulDstBottomScan ;bottom of destination rectangle
531: cmp edx,[ebx].pdev_rcl1WindowClip.yBottom
532: ;which comes first, the bottom of the
533: ; text rect or the bottom of the
534: ; current bank?
535: jl short @F ;text bottom comes first, so draw to
536: ; that; this is the last bank in text
537: mov edx,[ebx].pdev_rcl1WindowClip.yBottom
538: ;bank bottom comes first; draw to
539: ; bottom of bank
540: @@:
541: sub edx,ulDstTopScan ;# of scans to draw in bank
542: mov ulScanCount,edx
543:
544: call pfnStretchFn ;stretch the bitmap block that's in this bank
545:
546: ;-----------------------------------------------------------------------;
547: ; See if there are more banks to draw.
548: ;-----------------------------------------------------------------------;
549:
550: mov ebx,ppdev
551: mov eax,[ebx].pdev_rcl1WindowClip.yBottom ;is the text bottom in
552: cmp ulDstBottomScan,eax ; the current bank?
553: jnle short do_next_bank ;no, map in the next bank and draw
554: mov eax,1 ;success
555: ;@@@shouldn't return a value
556: done:
557: cRet vStretchBlt8bpp ;yes, so we're done
558:
559: align 4
560: do_next_bank:
561: mov ulDstTopScan,eax
562: sub edi,[ebx].pdev_pvBitmapStart ;convert from address to offset
563: ; within bitmap
564: ptrCall <dword ptr [ebx].pdev_pfnBankControl>,<ebx,eax,JustifyTop>
565: ;map in the bank (call preserves
566: ; EBX, ESI, and EDI)
567: add edi,[ebx].pdev_pvBitmapStart ;convert from offset within bitmap
568: ; to address (bitmap start just
569: ; moved)
570: jmp bank_loop ;we're ready to draw to the new
571: ; bank
572:
573: ;-----------------------------------------------------------------------;
574: ; Shrink in X and Y, xlat or noxlat, 8-bpp source, VGA dest
575: ;
576: ; On entry: ESI->first source pixel to copy from
577: ; EDI->first dest pixel to copy to
578: ; pulXlatVector = pointer to color translation array (xlat cases
579: ; only)
580: ; ulSrcMinNext = minimum offset from end of current source scan to
581: ; start of next source scan to stretch
582: ; lSrcNext = offset from start of one source scan to start of next
583: ; ulDestNext = offset from end of current dest scan to start of
584: ; next dest scan to stretch to
585: ; pfnRowVector = pointer to routine to call to stretch one scan
586: ; ulScanCount = # of scans to stretch
587: ; lYErrorTerm, ulYAdjUp, ulYAdjDown = Y DDA error term components
588: ;
589: ; On exit: ESI->next source pixel to copy from
590: ; EDI->next dest pixel to copy to
591: ; lYErrorTerm advanced for next scan
592: ;-----------------------------------------------------------------------;
593:
594: shrink_8bpp_loop:
595: sub ebx,ebx ;prepare EBX=0 for xlat-case row-drawing
596: ; routines
597: shrink_block_8bpp_loop:
598: mov edx,pulDDAArray ;point to array of skip values to use to scan
599: ; across the source
600: mov ecx,ulXStretchCount ;# of pixels or pixel pairs to copy to
601: push esi ;preserve source pointer
602: call pfnRowVector ;stretch/shrink this row
603: pop esi ;restore source pointer
604: add esi,ulSrcMinNext ;point to start of next source row, assuming
605: ; no extra row for error term turnover
606: mov eax,lYErrorTerm
607: add eax,ulYAdjUp ;advance the error term
608: jnc short @F ; didn't turn over (minimum step)
609: sub eax,ulYAdjDown ;turned over, adjust down and...
610: add esi,lSrcNext ; advance an extra scan (maximum step)
611: @@:
612: mov lYErrorTerm,eax ;remember the new error term
613: add edi,ulDestNext ;point to start of next destination row
614: dec ulScanCount ;count down scans
615: jnz shrink_block_8bpp_loop
616: retn
617:
618: ;-----------------------------------------------------------------------;
619: ; Single-row optimizations, called out of main stretch loops.
620: ;-----------------------------------------------------------------------;
621:
622: ;-----------------------------------------------------------------------;
623: ; Shrink in X
624: ; No xlat
625: ; 8-bit source
626: ; Writes a word at a time
627: ;
628: ; Input: ECX = number of pixel pairs to do, not counting leading and trailing
629: ; single pixels (except in narrow case, where ECX = number of
630: ; pixels, not pixel pairs)
631: ; EDX = pointer to pre-computed skip array
632: ; ESI = pointer to initial source pixel
633: ; EDI = pointer to initial destination pixel
634: ;
635: ; Output: ESI = pointer after last source pixel processed
636: ; EDI = pointer after last source pixel processed
637: ;
638: ; EBX and EBP are preserved
639: ; The contents of EAX, ECX, and EDX may be destroyed
640: ;-----------------------------------------------------------------------;
641:
642: ; No leading byte, no trailing byte.
643:
644: shrink_noxlat_8bpp_nl_nt:
645: shrink_noxlat_8bpp_nl_nt_pixel_loop:
646: mov al,[esi] ;get first source pixel
647: add esi,[edx] ;point to next source pixel
648: mov ah,[esi] ;get second source pixel
649: add esi,[edx+4] ;point to next source pixel
650: add edx,8 ;point to next skip entry
651: mov [edi],ax ;write both pixels to the destination
652: add edi,2 ;point to next destination pixel
653: dec ecx ;count down pixel pairs
654: jnz shrink_noxlat_8bpp_nl_nt_pixel_loop
655: retn
656:
657: ; Leading byte, no trailing byte.
658:
659: shrink_noxlat_8bpp_l_nt:
660: ;do the leading pixel
661: mov al,[esi] ;get the current source pixel
662: add esi,[edx] ;point to next source pixel
663: add edx,4 ;point to next skip entry
664: mov [edi],al ;write the pixel to the destination
665: inc edi ;point to next destination pixel
666: ;now do pixel pairs across the middle
667: shrink_noxlat_8bpp_l_nt_pixel_loop:
668: mov al,[esi] ;get first source pixel
669: add esi,[edx] ;point to next source pixel
670: mov ah,[esi] ;get second source pixel
671: add esi,[edx+4] ;point to next source pixel
672: add edx,8 ;point to next skip entry
673: mov [edi],ax ;write both pixels to the destination
674: add edi,2 ;point to next destination pixel
675: dec ecx ;count down pixel pairs
676: jnz shrink_noxlat_8bpp_l_nt_pixel_loop
677: retn
678:
679: ; Leading byte, trailing byte.
680:
681: shrink_noxlat_8bpp_l_t:
682: ;do the leading pixel
683: mov al,[esi] ;get current source pixel
684: add esi,[edx] ;point to next source pixel
685: add edx,4 ;point to next skip entry
686: mov [edi],al ;write the pixel to the destination
687: inc edi ;point to next destination pixel
688: ;now do pixel pairs across the middle
689: shrink_noxlat_8bpp_l_t_pixel_loop:
690: mov al,[esi] ;get first source pixel
691: add esi,[edx] ;point to next source pixel
692: mov ah,[esi] ;get second source pixel
693: add esi,[edx+4] ;point to next source pixel
694: add edx,8 ;point to next skip entry
695: mov [edi],ax ;write both pixels to the destination
696: add edi,2 ;point to next destination pixel
697: dec ecx ;count down pixel pairs
698: jnz shrink_noxlat_8bpp_l_t_pixel_loop
699: ;do the trailing pixel
700: mov al,[esi] ;get current source pixel
701: add esi,[edx] ;point to next source pixel
702: add edx,4 ;point to next skip entry
703: mov [edi],al ;write the pixel to the destination
704: inc edi ;point to next destination pixel
705: retn
706:
707: ; No leading byte, trailing byte.
708:
709: shrink_noxlat_8bpp_nl_t:
710: shrink_noxlat_8bpp_nl_t_pixel_loop:
711: mov al,[esi] ;get first source pixel
712: add esi,[edx] ;point to next source pixel
713: mov ah,[esi] ;get second source pixel
714: add esi,[edx+4] ;point to next source pixel
715: add edx,8 ;point to next skip entry
716: mov [edi],ax ;write both pixels to the destination
717: add edi,2 ;point to next destination pixel
718: dec ecx ;count down pixel pairs
719: jnz shrink_noxlat_8bpp_nl_t_pixel_loop
720: ;do the trailing pixel
721: mov al,[esi] ;get current source pixel
722: add esi,[edx] ;point to next source pixel
723: add edx,4 ;point to next skip entry
724: mov [edi],al ;write the pixel to the destination
725: inc edi ;point to next destination pixel
726: retn
727:
728: ; Narrow case, a byte at a time.
729:
730: shrink_noxlat_8bpp_narrow:
731: shrink_noxlat_8bpp_narrow_pixel_loop:
732: mov al,[esi] ;get current source pixel
733: add esi,[edx] ;point to next source pixel
734: add edx,4 ;point to next skip entry
735: mov [edi],al ;write the pixel to the destination
736: inc edi ;point to next destination pixel
737: dec ecx ;count down pixels
738: jnz shrink_noxlat_8bpp_narrow_pixel_loop
739: retn
740:
741: ;-----------------------------------------------------------------------;
742: ; Shrink in X
743: ; Xlat
744: ; 8-bit source
745: ; Writes a word at a time
746: ;
747: ; Input: EBX upper three bytes = zero (0)
748: ; ECX = number of pixel pairs to do, not counting leading and trailing
749: ; single pixels (except in narrow case, where ECX = number of
750: ; pixels, not pixel pairs)
751: ; EDX = pointer to pre-computed skip array
752: ; ESI = pointer to initial source pixel
753: ; EDI = pointer to initial destination pixel
754: ; pulXlatVector = pointer to color translation array
755: ;
756: ; Output: ESI = pointer after last source pixel processed
757: ; EDI = pointer after last source pixel processed
758: ;
759: ; EBP is preserved
760: ; The upper three bytes of EBX are preserved
761: ; The contents of EAX, BL, ECX, and EDX may be destroyed
762: ;-----------------------------------------------------------------------;
763:
764: ; No leading byte, no trailing byte.
765:
766: shrink_xlat_8bpp_nl_nt:
767: push ebp ;***stack frame not available***
768: mov ebp,pulXlatVector ;point EBP to the translation table
769: shrink_xlat_8bpp_nl_nt_pixel_loop:
770: mov bl,[esi] ;get first source pixel
771: add esi,[edx] ;point to next source pixel
772: mov eax,[ebp+ebx*4] ;translate the pixel color
773: mov bl,[esi] ;get second source pixel
774: add esi,[edx+4] ;point to next source pixel
775: mov ah,[ebp+ebx*4] ;translate the pixel color
776: add edx,8 ;point to next skip entry
777: mov [edi],ax ;write both pixels to the destination
778: add edi,2 ;point to next destination pixel
779: dec ecx ;count down pixel pairs
780: jnz shrink_xlat_8bpp_nl_nt_pixel_loop
781: pop ebp ;***stack frame available***
782: retn
783:
784: ; Leading byte, no trailing byte.
785:
786: shrink_xlat_8bpp_l_nt:
787: push ebp ;***stack frame not available***
788: mov ebp,pulXlatVector ;point EBP to the translation table
789: ;do the leading pixel
790: mov bl,[esi] ;get first source pixel
791: add esi,[edx] ;point to next source pixel
792: mov eax,[ebp+ebx*4] ;translate the pixel color
793: add edx,4 ;point to next skip entry
794: mov [edi],al ;write the pixel to the destination
795: inc edi ;point to next destination pixel
796: ;now do pixel pairs across the middle
797: shrink_xlat_8bpp_l_nt_pixel_loop:
798: mov bl,[esi] ;get first source pixel
799: add esi,[edx] ;point to next source pixel
800: mov eax,[ebp+ebx*4] ;translate the pixel color
801: mov bl,[esi] ;get second source pixel
802: add esi,[edx+4] ;point to next source pixel
803: mov ah,[ebp+ebx*4] ;translate the pixel color
804: add edx,8 ;point to next skip entry
805: mov [edi],ax ;write both pixels to the destination
806: add edi,2 ;point to next destination pixel
807: dec ecx ;count down pixel pairs
808: jnz shrink_xlat_8bpp_l_nt_pixel_loop
809: pop ebp ;***stack frame available***
810: retn
811:
812: ; Leading byte, trailing byte.
813:
814: shrink_xlat_8bpp_l_t:
815: push ebp ;***stack frame not available***
816: mov ebp,pulXlatVector ;point EBP to the translation table
817: ;do the leading pixel
818: mov bl,[esi] ;get first source pixel
819: add esi,[edx] ;point to next source pixel
820: mov eax,[ebp+ebx*4] ;translate the pixel color
821: add edx,4 ;point to next skip entry
822: mov [edi],al ;write the pixel to the destination
823: inc edi ;point to next destination pixel
824: ;now do pixel pairs across the middle
825: shrink_xlat_8bpp_l_t_pixel_loop:
826: mov bl,[esi] ;get first source pixel
827: add esi,[edx] ;point to next source pixel
828: mov eax,[ebp+ebx*4] ;translate the pixel color
829: mov bl,[esi] ;get second source pixel
830: add esi,[edx+4] ;point to next source pixel
831: mov ah,[ebp+ebx*4] ;translate the pixel color
832: add edx,8 ;point to next skip entry
833: mov [edi],ax ;write both pixels to the destination
834: add edi,2 ;point to next destination pixel
835: dec ecx ;count down pixel pairs
836: jnz shrink_xlat_8bpp_l_t_pixel_loop
837: ;do the trailing pixel
838: mov bl,[esi] ;get first source pixel
839: add esi,[edx] ;point to next source pixel
840: mov eax,[ebp+ebx*4] ;translate the pixel color
841: add edx,4 ;point to next skip entry
842: mov [edi],al ;write the pixel to the destination
843: inc edi ;point to next destination pixel
844: pop ebp ;***stack frame available***
845: retn
846:
847: ; No leading byte, trailing byte.
848:
849: shrink_xlat_8bpp_nl_t:
850: push ebp ;***stack frame not available***
851: mov ebp,pulXlatVector ;point EBP to the translation table
852: shrink_xlat_8bpp_nl_t_pixel_loop:
853: mov bl,[esi] ;get first source pixel
854: add esi,[edx] ;point to next source pixel
855: mov eax,[ebp+ebx*4] ;translate the pixel color
856: mov bl,[esi] ;get second source pixel
857: add esi,[edx+4] ;point to next source pixel
858: mov ah,[ebp+ebx*4] ;translate the pixel color
859: add edx,8 ;point to next skip entry
860: mov [edi],ax ;write both pixels to the destination
861: add edi,2 ;point to next destination pixel
862: dec ecx ;count down pixel pairs
863: jnz shrink_xlat_8bpp_nl_t_pixel_loop
864: ;do the trailing pixel
865: mov bl,[esi] ;get first source pixel
866: add esi,[edx] ;point to next source pixel
867: mov eax,[ebp+ebx*4] ;translate the pixel color
868: add edx,4 ;point to next skip entry
869: mov [edi],al ;write the pixel to the destination
870: inc edi ;point to next destination pixel
871: pop ebp ;***stack frame available***
872: retn
873: ; Narrow case, a byte at a time.
874:
875: shrink_xlat_8bpp_narrow:
876: push ebp ;***stack frame not available***
877: mov ebp,pulXlatVector ;point EBP to the translation table
878: shrink_xlat_8bpp_narrow_loop:
879: mov bl,[esi] ;get first source pixel
880: add esi,[edx] ;point to next source pixel
881: mov eax,[ebp+ebx*4] ;translate the pixel color
882: add edx,4 ;point to next skip entry
883: mov [edi],al ;write the pixel to the destination
884: inc edi ;point to next destination pixel
885: dec ecx ;count down pixels
886: jnz shrink_xlat_8bpp_narrow_loop
887: pop ebp ;***stack frame available***
888: retn
889:
890: endProc vStretchBlt8bpp
891:
892: public DoneFailed
893: public x_shrink
894: public check_y_shrink
895: public x_shrink_set_dda_loop
896: public x_shrink_set_dda_max
897: public x_shrink_set_dda_min
898: public x_shrink_set_dda_done
899: public y_shrink
900: public map_init_bank
901: public init_bank_mapped
902: public bank_loop
903: public done
904: public do_next_bank
905: public shrink_8bpp_loop
906: public shrink_block_8bpp_loop
907: public shrink_noxlat_8bpp_nl_nt
908: public shrink_noxlat_8bpp_nl_nt_pixel_loop
909: public shrink_noxlat_8bpp_l_nt
910: public shrink_noxlat_8bpp_l_nt_pixel_loop
911: public shrink_noxlat_8bpp_l_t
912: public shrink_noxlat_8bpp_l_t_pixel_loop
913: public shrink_noxlat_8bpp_nl_t
914: public shrink_noxlat_8bpp_nl_t_pixel_loop
915: public shrink_noxlat_8bpp_narrow
916: public shrink_noxlat_8bpp_narrow_pixel_loop
917: public shrink_xlat_8bpp_nl_nt
918: public shrink_xlat_8bpp_nl_nt_pixel_loop
919: public shrink_xlat_8bpp_l_nt
920: public shrink_xlat_8bpp_l_nt_pixel_loop
921: public shrink_xlat_8bpp_l_t
922: public shrink_xlat_8bpp_l_t_pixel_loop
923: public shrink_xlat_8bpp_nl_t
924: public shrink_xlat_8bpp_nl_t_pixel_loop
925: public shrink_xlat_8bpp_narrow
926: public shrink_xlat_8bpp_narrow_loop
927:
928: end
929:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.