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.
932 lines
45 KiB
932 lines
45 KiB
;---------------------------Module-Header------------------------------;
|
|
; Module Name: stretch.asm
|
|
;
|
|
; Copyright (c) 1992 Microsoft Corporation
|
|
;-----------------------------------------------------------------------;
|
|
;-----------------------------------------------------------------------;
|
|
; INT vStretchBlt8bpp(PPDEV ppdev, PBYTE pSrc, LONG lSrcNext,
|
|
; PRECTL prclSrc, PRECTL prclDest, PRECTL prclDestClip,
|
|
; PULONG pulXlatVector)
|
|
; Input:
|
|
;
|
|
; Performs accelerated stretch blts from 8-bit DIBs to 256-color VGA
|
|
; display memory.
|
|
;-----------------------------------------------------------------------;
|
|
; Note: Does not handle source clipping.
|
|
;
|
|
; Note: Does not yet handle expansion, only shrinking.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
comment $
|
|
|
|
***
|
|
|
|
Note: in the noxlat loop, EBX isn't altered, so it could be used for
|
|
something else, like the scan line count. This isn't done currently
|
|
because the scan-line loop is shared by the xlat and noxlat cases, and
|
|
the xlat cases do alter EBX; separate loops would be needed in order
|
|
to perform this optimization.
|
|
|
|
commend $
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.386
|
|
|
|
ifndef DOS_PLATFORM
|
|
.model small,c
|
|
else
|
|
ifdef STD_CALL
|
|
.model small,c
|
|
else
|
|
.model small,pascal
|
|
endif; STD_CALL
|
|
endif; DOS_PLATFORM
|
|
|
|
assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
|
|
assume fs:nothing,gs:nothing
|
|
|
|
.xlist
|
|
include stdcall.inc ;calling convention cmacros
|
|
include i386\strucs.inc
|
|
include i386\driver.inc
|
|
|
|
.list
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.data
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.code
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc vStretchBlt8bpp,28,< \
|
|
uses esi edi ebx, \
|
|
ppdev:ptr, \
|
|
pSrc:ptr, \
|
|
lSrcNext:dword, \
|
|
prclSrc:ptr, \
|
|
prclDest:ptr, \
|
|
prclDestClip:ptr, \
|
|
pulXlatVector:dword >
|
|
|
|
local pulDDAArray:dword ;pointer to array of n and n+1
|
|
; values generated by DDA, used to
|
|
; advance across source
|
|
local ulXStretchCount:dword ;# of pixels or pixel pair to copy to
|
|
; (pixel pairs except in narrow
|
|
; cases; doesn't include leading or
|
|
; trailing single pixels in pixel
|
|
; pair cases)
|
|
local ulDestNext:dword ;offset from last dest pixel on one
|
|
; scan to first on next
|
|
local ulSrcMinNext:dword ;offset from start of one source scan
|
|
; to start of next scan that's skipped
|
|
; to by minimum DDA advance (basically,
|
|
; skips over n scans when DDA advances
|
|
; either n or n+1 scans)
|
|
local lYErrorTerm:dword ;current error term for the DDA in Y
|
|
local ulYAdjUp:dword ;error term adjust up for advancing
|
|
; DDA in Y
|
|
local ulYAdjDown:dword ;error term adjust down for advancing
|
|
; DDA in Y
|
|
local ulDstTopScan:dword ;top scan of dest text rect in
|
|
; current bank
|
|
local ulDstBottomScan :dword ;bottom scan line of dest rectangle
|
|
local ulScanCount:dword ;# of scans to stretch in current
|
|
; bank
|
|
local pfnRowVector:dword ;pointer to routine to be used to
|
|
; stretch each row
|
|
local pfnStretchFn:dword ;pointer to routine to do a bank's
|
|
; worth of stretching
|
|
local ulSrcTopScan:dword ;top scan line of source from which
|
|
; to copy (after clipping, if needed)
|
|
local ulYMinStep:dword ;minimum # of scans to skip in source
|
|
; when advancing dest one scan
|
|
local lXDstRight:dword ;right edge of dest area to which to
|
|
; stretch, accounting for clipping
|
|
local lXDstLeft:dword ;left edge of dest area to which to
|
|
; stretch, accounting for clipping
|
|
local ulXAdjUp:dword ;X error term adjust up
|
|
local ulXMinStep:dword ;X minimum step per dest 1-pixel step
|
|
local ulXAdjDown:dword ;X error term adjust down
|
|
local lXSrcRight:dword ;right edge of source area from which
|
|
; to stretch, accounting for clipping
|
|
local lXSrcLeft:dword ;left edge of source area from which to
|
|
; stretch, accounting for clipping
|
|
local pvBuf:dword ;local copy of ppdev->pvTmpBuf ptr
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov esi,ppdev
|
|
mov edi,[esi].pdev_pvTmpBuf
|
|
mov pvBuf,edi
|
|
|
|
mov esi,prclSrc
|
|
mov edi,prclDest
|
|
|
|
mov eax,[esi].xRight
|
|
mov edx,[esi].xLeft
|
|
mov lXSrcLeft,edx
|
|
sub eax,edx ;EAX = source width
|
|
mov ecx,[edi].xRight
|
|
mov lXDstRight,ecx
|
|
mov edx,[edi].xLeft
|
|
mov lXDstLeft,edx
|
|
sub ecx,edx ;ECX = dest width
|
|
|
|
cmp eax,ecx ;shrink or stretch in X?
|
|
jge short x_shrink ;shrink
|
|
;stretch
|
|
;@@@
|
|
DoneFailed::
|
|
sub eax,eax ;@@@shouldn't have to return a value
|
|
jmp done
|
|
|
|
;The destination is narrower than the source
|
|
x_shrink::
|
|
mov pfnStretchFn,offset shrink_8bpp_loop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Precalculate the DDA steps for X and store them in the temp buffer. We know
|
|
; these will fit in the temp buffer, because there are only, say, 2K steps
|
|
; max across the screen, and the temp buffer is guaranteed to be more than
|
|
; 2K*4 = 8K bytes long.
|
|
;
|
|
; At this point, EAX = source width, ECX = destination width
|
|
;-----------------------------------------------------------------------;
|
|
|
|
sub edx,edx ;prepare for division
|
|
div ecx ;SourceDeltaX / DestDeltaX
|
|
mov ulXMinStep,eax ;EAX = minimum step in source for 1 dest step
|
|
|
|
mov esi,edx ;set aside SourceDeltaX % DestDeltaX
|
|
add edx,edx ;scale up ulXAdjUp by 2 so we can handle a
|
|
; half-pixel advance
|
|
mov ulXAdjUp,edx ;ulXAdjUp = (SourceDeltaX % DestDeltaX)*2
|
|
|
|
;prestep source X coord and error term by 1/2
|
|
; a destination pixel, so we pick the source
|
|
; pixel that most closely matches the center
|
|
; of each destination pixel
|
|
|
|
;step by 1/2 the whole source pixel advance
|
|
; per destination step
|
|
shr eax,1 ;minimum step/2
|
|
jnc short @F ;odd
|
|
;even
|
|
add esi,ecx ;advance error term for 1/2 of the source
|
|
; pixel we just split (by DestDeltaX)
|
|
@@:
|
|
add lXSrcLeft,eax ;advance 1/2 minimum step in source
|
|
add ecx,ecx ;scale up DestDeltaX by 2 so we can handle a
|
|
; half-pixel advance
|
|
mov ulXAdjDown,ecx ;ulXAdjDown = DestDeltaX*2
|
|
|
|
sub esi,ecx ;initial error term = -(DestDeltaX*2) + 1/2
|
|
; normal error term step (for 1/2 pixel dest
|
|
; advance effect on error term; note that 1/2
|
|
; effect on whole source pixels has already
|
|
; been accounted for)
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Clip to the dest in X, if necessary.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,prclDestClip
|
|
and ebx,ebx ;any clipping?
|
|
jz short x_clip_done ;no, all set
|
|
mov eax,[ebx].xRight ;right clip edge
|
|
cmp eax,lXDstRight ;is the right edge clipped?
|
|
jge short check_x_left_clip ;no
|
|
;right edge is clipped
|
|
mov lXDstRight,eax ;set the clipped right edge
|
|
check_x_left_clip:
|
|
mov eax,[ebx].xLeft ;left clip edge
|
|
cmp eax,lXDstLeft ;is the left edge clipped?
|
|
jle short check_x_not_fully_clipped ;no
|
|
;left edge is clipped
|
|
mov edx,lXDstLeft ;get the unclipped dest left edge
|
|
mov lXDstLeft,eax ;set the clipped dest left edge
|
|
;now figure out how many source pixels
|
|
; were clipped, and advance the error
|
|
; term appropriately
|
|
sub eax,edx ;# of dest pixels clipped
|
|
mov ecx,eax ;set aside # of dest pixels to skip
|
|
mul ulXAdjUp ;# of adjust ups in the course of the
|
|
; skipped pixels
|
|
add esi,eax ;EDX:ESI = error term after skipping
|
|
adc edx,-1 ;(the initial error term is negative;
|
|
; this stretches it to 64 bits)
|
|
jnc short check_x_not_fully_clipped ;didn't turn over even once
|
|
mov eax,esi ;EDX:EAX = error term after skipping
|
|
div ulXAdjDown ;EAX = # of times to adjust down
|
|
; while skipping pixels, minus 1
|
|
sub edx,ulXAdjDown ;do the last adjust down, to cross
|
|
; back into negative territory where
|
|
; the error term belongs
|
|
mov esi,edx ;error term at new, clipped dest left
|
|
; edge
|
|
inc eax ;count the last adjust down (# of times
|
|
; source error turned over while
|
|
; advancing to the clipped left edge)
|
|
imul ecx,ulXMinStep ;# of whole pixels skipped in source
|
|
; while advancing to dest clip left
|
|
; edge
|
|
add eax,ecx ;total # of pixels skipped in source
|
|
; while advancing to dest clip left
|
|
; edge
|
|
add lXSrcLeft,eax ;advance the source left edge to match
|
|
; advancing the destination left edge
|
|
; to the left edge of the clip
|
|
; rectangle
|
|
check_x_not_fully_clipped:
|
|
mov eax,lXDstLeft
|
|
cmp lXDstRight,eax ;is the destination fully x-clipped?
|
|
jle done ;yes, nothing to draw
|
|
x_clip_done:
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Now actually generate the (possibly clipped) X DDA skip array
|
|
;
|
|
; At this point, ESI = X error term for left edge (accounting for any
|
|
; X clipping that has occurred)
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,ulXMinStep
|
|
mov edi,pvBuf ;we'll store the DDA steps in the temp
|
|
mov pulDDAArray,edi ; buffer
|
|
|
|
mov edx,ulXAdjUp
|
|
mov ebx,ulXAdjDown
|
|
mov ecx,lXDstRight
|
|
sub ecx,lXDstLeft ;ECX = # of pixels per dest scan
|
|
push ecx ;remember # of dest pixels across
|
|
push ebp ;preserve stack frame pointer
|
|
lea ebp,[eax+1] ;maximum step
|
|
;***stack frame unavailable***
|
|
x_shrink_set_dda_loop::
|
|
add esi,edx ;adjust the error term up
|
|
jnc short x_shrink_set_dda_min ;didn't turn over, so advance
|
|
; minimum step
|
|
x_shrink_set_dda_max::
|
|
sub esi,ebx ;turned over; adjust error term back down
|
|
mov [edi],ebp ;advance by maximum step
|
|
add edi,4 ;point to next DDA array storage location
|
|
dec ecx ;count down steps
|
|
jz short x_shrink_set_dda_done ;no more steps
|
|
add esi,edx ;adjust the error term up
|
|
jc x_shrink_set_dda_max ;did turn over, so advance maximum step
|
|
x_shrink_set_dda_min::
|
|
mov [edi],eax ;advance by minimum step
|
|
add edi,4 ;point to next DDA array storage location
|
|
dec ecx ;count down steps
|
|
jnz x_shrink_set_dda_loop
|
|
x_shrink_set_dda_done::
|
|
mov dword ptr [edi],0 ;mark the end of the DDA
|
|
pop ebp ;restore stack frame pointer
|
|
;***stack frame available***
|
|
pop ecx ;retrieve # of dest pixels across
|
|
|
|
mov edi,prclDest
|
|
cmp pulXlatVector,0 ;translation?
|
|
jz short x_shrink_noxlat ;no
|
|
;yes
|
|
cmp ecx,3 ;narrow case?
|
|
ja short @F ;no
|
|
mov pfnRowVector,offset shrink_xlat_8bpp_narrow ;narrow case
|
|
mov ulXStretchCount,ecx ;do all dest pixels one at a time
|
|
jmp check_y_shrink
|
|
@@: ;not narrow case; figure out which wide case,
|
|
; based on the need to perform as many word-
|
|
; aligned writes to display memory as possible
|
|
mov edx,ecx
|
|
test [edi].xLeft,1 ;starting at an odd destination address?
|
|
jnz short x_shrink_xlat_leading ;yes, need leading pixel
|
|
mov pfnRowVector,offset shrink_xlat_8bpp_nl_nt
|
|
;assume no leading or trailing pixels
|
|
shr edx,1 ;destination width in pixel pairs
|
|
mov ulXStretchCount,edx ;count of pixel pairs to draw
|
|
jnc short check_y_shrink ;no leading or trailing pixels
|
|
mov pfnRowVector,offset shrink_xlat_8bpp_nl_t
|
|
;no leading pixel, is a trailing pixel
|
|
jmp short check_y_shrink
|
|
x_shrink_xlat_leading: ;there is a leading pixel
|
|
mov pfnRowVector,offset shrink_xlat_8bpp_l_nt
|
|
;assume no trailing pixel
|
|
shr edx,1 ;destination width in pixel pairs
|
|
mov ulXStretchCount,edx ;count of pixel pairs to draw
|
|
jc short check_y_shrink ;no trailing pixel
|
|
mov pfnRowVector,offset shrink_xlat_8bpp_l_t
|
|
;both leading and trailing pixels
|
|
dec edx ;we'll do one pixel pair in the form
|
|
; of the leading/trailing pixel pair
|
|
mov ulXStretchCount,edx ;count of pixel pairs to draw
|
|
jmp short check_y_shrink
|
|
|
|
x_shrink_noxlat: ;no translation
|
|
cmp ecx,3 ;narrow case?
|
|
ja short @F ;no
|
|
mov pfnRowVector,offset shrink_noxlat_8bpp_narrow ;narrow case
|
|
mov ulXStretchCount,ecx ;do all dest pixels one at a time
|
|
jmp short check_y_shrink
|
|
@@: ;not narrow case; figure out which wide case,
|
|
; based on the need to perform as many word-
|
|
; aligned writes to display memory as possible
|
|
mov edx,ecx
|
|
test [edi].xLeft,1 ;starting at an odd destination address?
|
|
jnz short x_shrink_noxlat_leading ;yes, need leading pixel
|
|
mov pfnRowVector,offset shrink_noxlat_8bpp_nl_nt
|
|
;assume no leading or trailing pixels
|
|
shr edx,1 ;destination width in pixel pairs
|
|
mov ulXStretchCount,edx ;count of pixel pairs to draw
|
|
jnc short check_y_shrink ;no leading or trailing pixels
|
|
mov pfnRowVector,offset shrink_noxlat_8bpp_nl_t
|
|
;no leading pixel, is a trailing pixel
|
|
jmp short check_y_shrink
|
|
x_shrink_noxlat_leading: ;there is a leading pixel
|
|
mov pfnRowVector,offset shrink_noxlat_8bpp_l_nt
|
|
;assume no trailing pixel
|
|
shr edx,1 ;destination width in pixel pairs
|
|
mov ulXStretchCount,edx ;count of pixel pairs to draw
|
|
jc short check_y_shrink ;no trailing pixel
|
|
mov pfnRowVector,offset shrink_noxlat_8bpp_l_t
|
|
;both leading and trailing pixels
|
|
dec edx ;we'll do one pixel pair in the form
|
|
; of the leading/trailing pixel pair
|
|
mov ulXStretchCount,edx ;count of pixel pairs to draw
|
|
|
|
check_y_shrink::
|
|
|
|
mov esi,edi ;ESI->prclDest
|
|
mov edi,prclSrc ;EDI->prclSrc
|
|
mov eax,[edi].yBottom
|
|
mov ecx,[edi].yTop
|
|
mov ulSrcTopScan,ecx
|
|
sub eax,ecx ;EAX = source height
|
|
mov ecx,[esi].yBottom
|
|
mov ulDstBottomScan,ecx
|
|
mov edx,[esi].yTop
|
|
mov ulDstTopScan,edx
|
|
sub ecx,edx ;ECX = dest height
|
|
|
|
cmp eax,ecx ;shrink or stretch in Y?
|
|
jge short y_shrink ;shrink
|
|
;stretch
|
|
;@@@
|
|
sub eax,eax ;@@@shouldn't have to return a value
|
|
jmp done
|
|
|
|
;The destination is shorter than the source; calculate the error term values
|
|
; for advancing through the source on a per-dest-scan-line basis.
|
|
y_shrink::
|
|
sub edx,edx ;prepare for division
|
|
div ecx ;SourceDeltaY/DestDeltaY
|
|
mov ulYMinStep,eax ;EAX = minimum step in source for 1 dest step
|
|
|
|
mov ebx,edx ;set aside SourceDeltaY % DestDeltaY
|
|
add edx,edx ;scale up ulYAdjUp by 2 so we can handle a
|
|
; half-pixel advance
|
|
mov ulYAdjUp,edx ;ulYAdjUp = (SourceDeltaY % DestDeltaY)*2
|
|
|
|
imul lSrcNext ;(minimum step * source scan width in bytes)
|
|
mov ulSrcMinNext,eax ; = minimum offset by which to advance from
|
|
; one scan to the next
|
|
|
|
;prestep source X coord and error term by 1/2
|
|
; a destination pixel, so we pick the source
|
|
; pixel that most closely matches the center
|
|
; of each destination pixel
|
|
|
|
;step by 1/2 the whole source pixel advance
|
|
; per destination step
|
|
mov eax,ulYMinStep ;retrieve minimum step
|
|
shr eax,1 ;minimum step/2
|
|
jnc short @F ;odd
|
|
;even
|
|
add ebx,ecx ;advance error term for 1/2 of the source
|
|
; pixel we just split
|
|
@@:
|
|
add ulSrcTopScan,eax ;advance 1/2 minimum step in source
|
|
|
|
add ecx,ecx ;scale up DestDeltaY by 2 so we can handle a
|
|
; half-pixel advance
|
|
mov ulYAdjDown,ecx ;ulYAdjDown = DestDeltaY*2
|
|
|
|
sub ebx,ecx ;initial error term = -(DestDeltaY*2) + 1/2
|
|
; normal error term step (for 1/2 pixel dest
|
|
; advance effect on error term; note that 1/2
|
|
; effect on whole source pixels has already
|
|
; been accounted for)
|
|
mov lYErrorTerm,ebx
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Clip in Y, if necessary.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,prclDestClip
|
|
and ebx,ebx ;any clipping?
|
|
jz short y_clip_done ;no, all set
|
|
mov eax,[ebx].yBottom ;yes, clipping
|
|
;see if the dest is clipped off the
|
|
; bottom
|
|
cmp ulDstBottomScan,eax ;is the bottom clipped?
|
|
jle short check_y_top_clip ;no, check the top
|
|
mov ulDstBottomScan,eax ;yes, set the new bottom
|
|
check_y_top_clip:
|
|
;see if the dest is clipped off the
|
|
; top
|
|
mov eax,[ebx].yTop
|
|
cmp ulDstTopScan,eax ;is the top clipped?
|
|
jge short check_y_not_fully_clipped ;no
|
|
;yes, so advance the top scan and the
|
|
; error term accordingly
|
|
mov ulDstTopScan,eax ;top of clipped destination rectangle
|
|
sub eax,[esi].yTop ;# of destination scans to skip
|
|
mov ecx,eax ;set aside # of dest scans to skip
|
|
mul ulYAdjUp ;# of adjust ups in the course of the
|
|
; skipped scans
|
|
add eax,lYErrorTerm ;EDX:EAX = error term after skipping
|
|
adc edx,-1 ;(the initial error term is negative;
|
|
; this stretches it to 64 bits)
|
|
jnc short check_y_not_fully_clipped ;didn't turn over even once
|
|
div ulYAdjDown ;EAX = # of times to adjust down
|
|
; while skipping scans, minus 1
|
|
sub edx,ulYAdjDown ;do the last adjust down, to cross
|
|
; back into negative territory where
|
|
; the error term belongs
|
|
mov lYErrorTerm,edx ;error term at new, clipped dest top
|
|
inc eax ;count the last adjust down (# of
|
|
; times source error has turned over)
|
|
imul ecx,ulYMinStep ;# of whole steps in source while
|
|
; advancing to dest clip top
|
|
add eax,ecx ;total # of scans skipped in source
|
|
; while advancing to dest clip top
|
|
add ulSrcTopScan,eax ;advance the source top edge to match
|
|
; advancing the destination top edge to
|
|
; the top of the clip rectangle
|
|
check_y_not_fully_clipped:
|
|
mov eax,ulDstTopScan
|
|
cmp ulDstBottomScan,eax ;is the destination fully y-clipped?
|
|
jle done ;yes, nothing to draw
|
|
y_clip_done:
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Calculate the offset of the initial destination pixel.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,ppdev
|
|
mov eax,ulDstTopScan ;top scan line of text
|
|
mov esi,[ebx].pdev_lDeltaScreen
|
|
mul esi
|
|
mov edi,lXDstLeft
|
|
mov ecx,lXDstRight
|
|
sub ecx,edi ;dest width
|
|
sub esi,ecx ;dest width - width of a dest scan to stretch
|
|
mov ulDestNext,esi ;offset from end of one dest stretched
|
|
; scan to start of next
|
|
add edi,eax
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Map in the bank containing the top scan of the text, if it's not
|
|
; mapped in already.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,ulDstTopScan ;top scan line of text
|
|
cmp eax,[ebx].pdev_rcl1WindowClip.yTop ;is text top less than
|
|
; current bank?
|
|
jl short map_init_bank ;yes, map in proper bank
|
|
cmp eax,[ebx].pdev_rcl1WindowClip.yBottom ;text top greater than
|
|
; current bank?
|
|
jl short init_bank_mapped ;no, proper bank already mapped
|
|
map_init_bank::
|
|
|
|
; Map in the bank containing the top scan line of the destination.
|
|
; Preserves EBX, ESI, and EDI.
|
|
|
|
ptrCall <dword ptr [ebx].pdev_pfnBankControl>,<ebx,eax,JustifyTop>
|
|
|
|
init_bank_mapped::
|
|
|
|
add edi,[ebx].pdev_pvBitmapStart ;initial destination address
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Calculate the offset of the initial source pixel.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov esi,prclSrc
|
|
mov eax,lSrcNext
|
|
imul ulSrcTopScan
|
|
mov esi,lXSrcLeft
|
|
add esi,eax
|
|
add esi,pSrc
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Main loop for processing stretch blt in each bank.
|
|
;
|
|
; At start of loop, EBX->ppdev, ESI->current src, EDI->current dst
|
|
;-----------------------------------------------------------------------;
|
|
|
|
bank_loop::
|
|
mov edx,ulDstBottomScan ;bottom of destination rectangle
|
|
cmp edx,[ebx].pdev_rcl1WindowClip.yBottom
|
|
;which comes first, the bottom of the
|
|
; text rect or the bottom of the
|
|
; current bank?
|
|
jl short @F ;text bottom comes first, so draw to
|
|
; that; this is the last bank in text
|
|
mov edx,[ebx].pdev_rcl1WindowClip.yBottom
|
|
;bank bottom comes first; draw to
|
|
; bottom of bank
|
|
@@:
|
|
sub edx,ulDstTopScan ;# of scans to draw in bank
|
|
mov ulScanCount,edx
|
|
|
|
call pfnStretchFn ;stretch the bitmap block that's in this bank
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; See if there are more banks to draw.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,ppdev
|
|
mov eax,[ebx].pdev_rcl1WindowClip.yBottom ;is the text bottom in
|
|
cmp ulDstBottomScan,eax ; the current bank?
|
|
jnle short do_next_bank ;no, map in the next bank and draw
|
|
mov eax,1 ;success
|
|
;@@@shouldn't return a value
|
|
done::
|
|
cRet vStretchBlt8bpp ;yes, so we're done
|
|
|
|
do_next_bank::
|
|
mov ulDstTopScan,eax
|
|
sub edi,[ebx].pdev_pvBitmapStart ;convert from address to offset
|
|
; within bitmap
|
|
ptrCall <dword ptr [ebx].pdev_pfnBankControl>,<ebx,eax,JustifyTop>
|
|
;map in the bank (call preserves
|
|
; EBX, ESI, and EDI)
|
|
add edi,[ebx].pdev_pvBitmapStart ;convert from offset within bitmap
|
|
; to address (bitmap start just
|
|
; moved)
|
|
jmp bank_loop ;we're ready to draw to the new
|
|
; bank
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Shrink in X and Y, xlat or noxlat, 8-bpp source, VGA dest
|
|
;
|
|
; On entry: ESI->first source pixel to copy from
|
|
; EDI->first dest pixel to copy to
|
|
; pulXlatVector = pointer to color translation array (xlat cases
|
|
; only)
|
|
; ulSrcMinNext = minimum offset from end of current source scan to
|
|
; start of next source scan to stretch
|
|
; lSrcNext = offset from start of one source scan to start of next
|
|
; ulDestNext = offset from end of current dest scan to start of
|
|
; next dest scan to stretch to
|
|
; pfnRowVector = pointer to routine to call to stretch one scan
|
|
; ulScanCount = # of scans to stretch
|
|
; lYErrorTerm, ulYAdjUp, ulYAdjDown = Y DDA error term components
|
|
;
|
|
; On exit: ESI->next source pixel to copy from
|
|
; EDI->next dest pixel to copy to
|
|
; lYErrorTerm advanced for next scan
|
|
;-----------------------------------------------------------------------;
|
|
|
|
shrink_8bpp_loop::
|
|
sub ebx,ebx ;prepare EBX=0 for xlat-case row-drawing
|
|
; routines
|
|
shrink_block_8bpp_loop::
|
|
mov edx,pulDDAArray ;point to array of skip values to use to scan
|
|
; across the source
|
|
mov ecx,ulXStretchCount ;# of pixels or pixel pairs to copy to
|
|
push esi ;preserve source pointer
|
|
call pfnRowVector ;stretch/shrink this row
|
|
pop esi ;restore source pointer
|
|
add esi,ulSrcMinNext ;point to start of next source row, assuming
|
|
; no extra row for error term turnover
|
|
mov eax,lYErrorTerm
|
|
add eax,ulYAdjUp ;advance the error term
|
|
jnc short @F ; didn't turn over (minimum step)
|
|
sub eax,ulYAdjDown ;turned over, adjust down and...
|
|
add esi,lSrcNext ; advance an extra scan (maximum step)
|
|
@@:
|
|
mov lYErrorTerm,eax ;remember the new error term
|
|
add edi,ulDestNext ;point to start of next destination row
|
|
dec ulScanCount ;count down scans
|
|
jnz shrink_block_8bpp_loop
|
|
retn
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Single-row optimizations, called out of main stretch loops.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Shrink in X
|
|
; No xlat
|
|
; 8-bit source
|
|
; Writes a word at a time
|
|
;
|
|
; Input: ECX = number of pixel pairs to do, not counting leading and trailing
|
|
; single pixels (except in narrow case, where ECX = number of
|
|
; pixels, not pixel pairs)
|
|
; EDX = pointer to pre-computed skip array
|
|
; ESI = pointer to initial source pixel
|
|
; EDI = pointer to initial destination pixel
|
|
;
|
|
; Output: ESI = pointer after last source pixel processed
|
|
; EDI = pointer after last source pixel processed
|
|
;
|
|
; EBX and EBP are preserved
|
|
; The contents of EAX, ECX, and EDX may be destroyed
|
|
;-----------------------------------------------------------------------;
|
|
|
|
; No leading byte, no trailing byte.
|
|
|
|
shrink_noxlat_8bpp_nl_nt::
|
|
shrink_noxlat_8bpp_nl_nt_pixel_loop::
|
|
mov al,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov ah,[esi] ;get second source pixel
|
|
add esi,[edx+4] ;point to next source pixel
|
|
add edx,8 ;point to next skip entry
|
|
mov [edi],ax ;write both pixels to the destination
|
|
add edi,2 ;point to next destination pixel
|
|
dec ecx ;count down pixel pairs
|
|
jnz shrink_noxlat_8bpp_nl_nt_pixel_loop
|
|
retn
|
|
|
|
; Leading byte, no trailing byte.
|
|
|
|
shrink_noxlat_8bpp_l_nt::
|
|
;do the leading pixel
|
|
mov al,[esi] ;get the current source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
;now do pixel pairs across the middle
|
|
shrink_noxlat_8bpp_l_nt_pixel_loop::
|
|
mov al,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov ah,[esi] ;get second source pixel
|
|
add esi,[edx+4] ;point to next source pixel
|
|
add edx,8 ;point to next skip entry
|
|
mov [edi],ax ;write both pixels to the destination
|
|
add edi,2 ;point to next destination pixel
|
|
dec ecx ;count down pixel pairs
|
|
jnz shrink_noxlat_8bpp_l_nt_pixel_loop
|
|
retn
|
|
|
|
; Leading byte, trailing byte.
|
|
|
|
shrink_noxlat_8bpp_l_t::
|
|
;do the leading pixel
|
|
mov al,[esi] ;get current source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
;now do pixel pairs across the middle
|
|
shrink_noxlat_8bpp_l_t_pixel_loop::
|
|
mov al,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov ah,[esi] ;get second source pixel
|
|
add esi,[edx+4] ;point to next source pixel
|
|
add edx,8 ;point to next skip entry
|
|
mov [edi],ax ;write both pixels to the destination
|
|
add edi,2 ;point to next destination pixel
|
|
dec ecx ;count down pixel pairs
|
|
jnz shrink_noxlat_8bpp_l_t_pixel_loop
|
|
;do the trailing pixel
|
|
mov al,[esi] ;get current source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
retn
|
|
|
|
; No leading byte, trailing byte.
|
|
|
|
shrink_noxlat_8bpp_nl_t::
|
|
shrink_noxlat_8bpp_nl_t_pixel_loop::
|
|
mov al,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov ah,[esi] ;get second source pixel
|
|
add esi,[edx+4] ;point to next source pixel
|
|
add edx,8 ;point to next skip entry
|
|
mov [edi],ax ;write both pixels to the destination
|
|
add edi,2 ;point to next destination pixel
|
|
dec ecx ;count down pixel pairs
|
|
jnz shrink_noxlat_8bpp_nl_t_pixel_loop
|
|
;do the trailing pixel
|
|
mov al,[esi] ;get current source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
retn
|
|
|
|
; Narrow case, a byte at a time.
|
|
|
|
shrink_noxlat_8bpp_narrow::
|
|
shrink_noxlat_8bpp_narrow_pixel_loop::
|
|
mov al,[esi] ;get current source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
dec ecx ;count down pixels
|
|
jnz shrink_noxlat_8bpp_narrow_pixel_loop
|
|
retn
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Shrink in X
|
|
; Xlat
|
|
; 8-bit source
|
|
; Writes a word at a time
|
|
;
|
|
; Input: EBX upper three bytes = zero (0)
|
|
; ECX = number of pixel pairs to do, not counting leading and trailing
|
|
; single pixels (except in narrow case, where ECX = number of
|
|
; pixels, not pixel pairs)
|
|
; EDX = pointer to pre-computed skip array
|
|
; ESI = pointer to initial source pixel
|
|
; EDI = pointer to initial destination pixel
|
|
; pulXlatVector = pointer to color translation array
|
|
;
|
|
; Output: ESI = pointer after last source pixel processed
|
|
; EDI = pointer after last source pixel processed
|
|
;
|
|
; EBP is preserved
|
|
; The upper three bytes of EBX are preserved
|
|
; The contents of EAX, BL, ECX, and EDX may be destroyed
|
|
;-----------------------------------------------------------------------;
|
|
|
|
; No leading byte, no trailing byte.
|
|
|
|
shrink_xlat_8bpp_nl_nt::
|
|
push ebp ;***stack frame not available***
|
|
mov ebp,pulXlatVector ;point EBP to the translation table
|
|
shrink_xlat_8bpp_nl_nt_pixel_loop::
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
mov bl,[esi] ;get second source pixel
|
|
add esi,[edx+4] ;point to next source pixel
|
|
mov ah,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,8 ;point to next skip entry
|
|
mov [edi],ax ;write both pixels to the destination
|
|
add edi,2 ;point to next destination pixel
|
|
dec ecx ;count down pixel pairs
|
|
jnz shrink_xlat_8bpp_nl_nt_pixel_loop
|
|
pop ebp ;***stack frame available***
|
|
retn
|
|
|
|
; Leading byte, no trailing byte.
|
|
|
|
shrink_xlat_8bpp_l_nt::
|
|
push ebp ;***stack frame not available***
|
|
mov ebp,pulXlatVector ;point EBP to the translation table
|
|
;do the leading pixel
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
;now do pixel pairs across the middle
|
|
shrink_xlat_8bpp_l_nt_pixel_loop::
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
mov bl,[esi] ;get second source pixel
|
|
add esi,[edx+4] ;point to next source pixel
|
|
mov ah,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,8 ;point to next skip entry
|
|
mov [edi],ax ;write both pixels to the destination
|
|
add edi,2 ;point to next destination pixel
|
|
dec ecx ;count down pixel pairs
|
|
jnz shrink_xlat_8bpp_l_nt_pixel_loop
|
|
pop ebp ;***stack frame available***
|
|
retn
|
|
|
|
; Leading byte, trailing byte.
|
|
|
|
shrink_xlat_8bpp_l_t::
|
|
push ebp ;***stack frame not available***
|
|
mov ebp,pulXlatVector ;point EBP to the translation table
|
|
;do the leading pixel
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
;now do pixel pairs across the middle
|
|
shrink_xlat_8bpp_l_t_pixel_loop::
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
mov bl,[esi] ;get second source pixel
|
|
add esi,[edx+4] ;point to next source pixel
|
|
mov ah,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,8 ;point to next skip entry
|
|
mov [edi],ax ;write both pixels to the destination
|
|
add edi,2 ;point to next destination pixel
|
|
dec ecx ;count down pixel pairs
|
|
jnz shrink_xlat_8bpp_l_t_pixel_loop
|
|
;do the trailing pixel
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
pop ebp ;***stack frame available***
|
|
retn
|
|
|
|
; No leading byte, trailing byte.
|
|
|
|
shrink_xlat_8bpp_nl_t::
|
|
push ebp ;***stack frame not available***
|
|
mov ebp,pulXlatVector ;point EBP to the translation table
|
|
shrink_xlat_8bpp_nl_t_pixel_loop::
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
mov bl,[esi] ;get second source pixel
|
|
add esi,[edx+4] ;point to next source pixel
|
|
mov ah,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,8 ;point to next skip entry
|
|
mov [edi],ax ;write both pixels to the destination
|
|
add edi,2 ;point to next destination pixel
|
|
dec ecx ;count down pixel pairs
|
|
jnz shrink_xlat_8bpp_nl_t_pixel_loop
|
|
;do the trailing pixel
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
pop ebp ;***stack frame available***
|
|
retn
|
|
; Narrow case, a byte at a time.
|
|
|
|
shrink_xlat_8bpp_narrow::
|
|
push ebp ;***stack frame not available***
|
|
mov ebp,pulXlatVector ;point EBP to the translation table
|
|
shrink_xlat_8bpp_narrow_loop::
|
|
mov bl,[esi] ;get first source pixel
|
|
add esi,[edx] ;point to next source pixel
|
|
mov eax,[ebp+ebx*4] ;translate the pixel color
|
|
add edx,4 ;point to next skip entry
|
|
mov [edi],al ;write the pixel to the destination
|
|
inc edi ;point to next destination pixel
|
|
dec ecx ;count down pixels
|
|
jnz shrink_xlat_8bpp_narrow_loop
|
|
pop ebp ;***stack frame available***
|
|
retn
|
|
|
|
endProc vStretchBlt8bpp
|
|
|
|
public DoneFailed
|
|
public x_shrink
|
|
public check_y_shrink
|
|
public x_shrink_set_dda_loop
|
|
public x_shrink_set_dda_max
|
|
public x_shrink_set_dda_min
|
|
public x_shrink_set_dda_done
|
|
public y_shrink
|
|
public map_init_bank
|
|
public init_bank_mapped
|
|
public bank_loop
|
|
public done
|
|
public do_next_bank
|
|
public shrink_8bpp_loop
|
|
public shrink_block_8bpp_loop
|
|
public shrink_noxlat_8bpp_nl_nt
|
|
public shrink_noxlat_8bpp_nl_nt_pixel_loop
|
|
public shrink_noxlat_8bpp_l_nt
|
|
public shrink_noxlat_8bpp_l_nt_pixel_loop
|
|
public shrink_noxlat_8bpp_l_t
|
|
public shrink_noxlat_8bpp_l_t_pixel_loop
|
|
public shrink_noxlat_8bpp_nl_t
|
|
public shrink_noxlat_8bpp_nl_t_pixel_loop
|
|
public shrink_noxlat_8bpp_narrow
|
|
public shrink_noxlat_8bpp_narrow_pixel_loop
|
|
public shrink_xlat_8bpp_nl_nt
|
|
public shrink_xlat_8bpp_nl_nt_pixel_loop
|
|
public shrink_xlat_8bpp_l_nt
|
|
public shrink_xlat_8bpp_l_nt_pixel_loop
|
|
public shrink_xlat_8bpp_l_t
|
|
public shrink_xlat_8bpp_l_t_pixel_loop
|
|
public shrink_xlat_8bpp_nl_t
|
|
public shrink_xlat_8bpp_nl_t_pixel_loop
|
|
public shrink_xlat_8bpp_narrow
|
|
public shrink_xlat_8bpp_narrow_loop
|
|
|
|
end
|
|
|