342 lines
14 KiB
NASM
342 lines
14 KiB
NASM
;---------------------------Module-Header------------------------------;
|
|
;
|
|
; Module Name: dfb2dfb.asm
|
|
;
|
|
; Copyright (c) 1993 Microsoft Corporation
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; VOID vDFB2DFB(DEVSURF * pdsurfDst,
|
|
; DEVSURF * pdsurfSrc,
|
|
; RECTL * prclDst,
|
|
; POINTL * pptlSrc);
|
|
;
|
|
; Performs accelerated copies from one DFB to another.
|
|
;
|
|
; pdsurfDst = pointer to dest surface
|
|
; pdsurfSrc = pointer to source surface
|
|
; prclDst = pointer to rectangle describing target area of dest. DFB
|
|
; pptlSrc = pointer to point structure describing the upper left corner
|
|
; of the copy in the source DFB
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; Note: Assumes the destination rectangle has a positive height and width.
|
|
; Will not work properly if this is not the case.
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.386
|
|
|
|
.model small,c
|
|
|
|
assume ds:FLAT,es:FLAT,ss:FLAT
|
|
assume fs:nothing,gs:nothing
|
|
|
|
.xlist
|
|
include stdcall.inc ;calling convention cmacros
|
|
include i386\egavga.inc
|
|
include i386\strucs.inc
|
|
|
|
.list
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.data
|
|
|
|
extrn dfb_jLeftMasks:dword ; identical static table to DFB2VGA, so use it.
|
|
extrn dfb_jRightMasks:dword ; identical static table to DFB2VGA, so use it.
|
|
extrn dfb_pfnScanHandlers:dword ; identical static table to DFB2VGA, so use it.
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.code
|
|
|
|
_TEXT$01 SEGMENT DWORD USE32 PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc vDFB2DFB,16,< \
|
|
uses esi edi ebx, \
|
|
pdsurfDst: ptr DEVSURF, \
|
|
pdsurfSrc: ptr DEVSURF, \
|
|
prclDst: ptr RECTL, \
|
|
pptlSrc : ptr POINTL >
|
|
|
|
local pfnDrawScans:dword ;ptr to correct scan drawing function
|
|
local pSrc:dword ;pointer to working drawing src start
|
|
; address (either DFB or temp buffer)
|
|
local pDst:dword ;pointer to drawing dst start address
|
|
; copy are to be performed, as follows:
|
|
local sDfbInfo[size DFBBLT]:byte
|
|
|
|
|
|
TRAILING_PARTIAL equ 01h ;partial trailing word should be copied
|
|
LEADING_PARTIAL equ 02h ;partial leading word should be copied
|
|
SOME_SHIFT_NEEDED equ 04h ;either right or left shift needed
|
|
LEFT_SHIFT_NEEDED equ 08h ;required shift is to the left
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Point to the source start address (nearest dword equal or less).
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,pptlSrc ;point to coords of source upper left
|
|
mov esi,pdsurfSrc ;point to surface to copy from (DFB)
|
|
mov edi,pdsurfDst ;point to surface to copy to (DFB)
|
|
mov eax,[ebx].ptl_y
|
|
imul eax,[esi].dsurf_lNextScan ;offset in bitmap of top src rect scan
|
|
mov edx,[ebx].ptl_x
|
|
shr edx,3 ;source byte X address
|
|
and edx,not 1b ;round down to nearest word
|
|
add eax,edx ;offset in bitmap of first source word
|
|
add eax,[esi].dsurf_pvBitmapStart ;pointer to first source word
|
|
mov pSrc,eax
|
|
sub eax,eax
|
|
mov pDst,eax ;Init it to zero
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up various variables for the copy.
|
|
;
|
|
; At this point, EBX = pptlSrc, EDI = pdsurfDst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov esi,prclDst ;point to rectangle to which to copy
|
|
sub ecx,ecx ;accumulate copy control flags
|
|
mov eax,[esi].xLeft ;first, check for partial-word edges
|
|
and eax,1111b ;left edge pixel alignment
|
|
jz short @F ;whole byte, don't need leading mask
|
|
or ecx,LEADING_PARTIAL ;do need leading mask
|
|
@@:
|
|
mov edx,dfb_jLeftMasks[eax*4] ;mask to apply to source to clip
|
|
mov sDfbInfo.LeftMask,edx ;remember mask
|
|
|
|
mov eax,[esi].xRight
|
|
and eax,1111b ;right edge pixel alignment
|
|
jz short @F ;whole byte, don't need trailing mask
|
|
or ecx,TRAILING_PARTIAL ;do need trailing mask
|
|
@@:
|
|
mov edx,dfb_jRightMasks[eax*4] ;mask to apply to source to clip
|
|
mov sDfbInfo.RightMask,edx ;remember mask
|
|
|
|
|
|
|
|
dfb2dfb_detect_partials::
|
|
mov sDfbInfo.DstWidth,0 ;overwritten if any whole words
|
|
;now, see if there are only partial
|
|
; words, or maybe even only one partial
|
|
mov eax,[esi].xLeft
|
|
add eax,1111b
|
|
and eax,not 1111b ;round left up to nearest word
|
|
mov edx,[esi].xRight
|
|
and edx,not 1111b ;round right down to nearest word
|
|
sub edx,eax ;# of pixels, rounded to nearest word
|
|
; boundaries (not counting partials)
|
|
ja short dfb2dfb_check_whole_words ;there's at least one whole word
|
|
;there are no whole words; there may be
|
|
; only one partial word, or there may
|
|
; be two
|
|
|
|
|
|
jb short dfb2dfb_one_partial_only ;there is only one, partial word
|
|
;if the dest is left- or right-
|
|
; justified, then there's only one,
|
|
; partial word, otherwise there are two
|
|
; partial words
|
|
cmp dword ptr sDfbInfo.LeftMask,0ffffh ;left-justified in word?
|
|
jz short dfb2dfb_one_partial_only ;yes, so only one, partial word
|
|
cmp dword ptr sDfbInfo.RightMask,0ffffh ;right-justified in word?
|
|
jnz short dfb2dfb_set_copy_control_flags ;no, so there are two partial
|
|
; words, which is exactly what
|
|
; we're already set up to do
|
|
|
|
|
|
|
|
dfb2dfb_one_partial_only:: ; only one, partial word, so construct a
|
|
; single mask and set up to do just
|
|
; one, partial word
|
|
mov eax,sDfbInfo.LeftMask
|
|
and eax,sDfbInfo.RightMask ;intersect the masks
|
|
mov sDfbInfo.LeftMask,eax
|
|
mov ecx,LEADING_PARTIAL ;only one partial word, which we'll
|
|
; treat as leading
|
|
jmp short dfb2dfb_set_copy_control_flags ;the copy control flags are set
|
|
|
|
dfb2dfb_check_whole_words::
|
|
;finally, calculate the number of whole
|
|
; words we'll process
|
|
mov eax,[esi].xLeft
|
|
add eax,1111b
|
|
shr eax,4 ;round left up to nearest word
|
|
mov edx,[esi].xRight
|
|
shr edx,4 ;round down to nearest word
|
|
sub edx,eax ;# of whole aligned words
|
|
|
|
mov sDfbInfo.DstWidth,edx ;save count of whole words
|
|
|
|
dfb2dfb_set_copy_control_flags::
|
|
|
|
; mov ulCopyControlFlags,ecx
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Determine whether any shift is needed to align the source with the
|
|
; destination.
|
|
;
|
|
; At this point, EBX = pptlSrc, ECX = Copy Control Flags
|
|
; ESI = prclDst, EDI = pdsurfDst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov edx,[ebx].ptl_x
|
|
and edx,1111b ;source X modulo 16
|
|
mov eax,[esi].xLeft
|
|
and eax,1111b ;dest X modulo 16
|
|
sub eax,edx ;(dest X modulo 16) - (src X modulo 16)
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Start optimization for byte aligned cases. Code works without this
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cmp eax,8
|
|
jne short @F
|
|
;
|
|
; Src starts in lower byte, Dst starts in upper byte
|
|
;
|
|
dec pSrc ;add unused first byte to src
|
|
sub eax,eax ;set alignment = 0
|
|
jmp dfb2dfb_done_with_byte_aligned_optimze
|
|
@@:
|
|
cmp eax,-8
|
|
jne short @F
|
|
;
|
|
; Src starts in upper byte, Dst starts in lower byte
|
|
;
|
|
inc pSrc ;remove unused first byte of src
|
|
sub eax,eax ;set alignment = 0
|
|
@@:
|
|
dfb2dfb_done_with_byte_aligned_optimze:
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; End optimization for byte aligned cases.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov sDfbInfo.AlignShift,eax ;remember the shift
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set pfnDrawScans to appropriate function:
|
|
;
|
|
; 0 0 ... 0 0 1 1 1 1
|
|
; | | | |______ trailing partial
|
|
; | | |________ leading partial
|
|
; |_|__________ align index 00 - no align needed
|
|
; 01 - right shift needed
|
|
; 10 - invalid
|
|
; 11 - left shift needed
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cmp sDfbInfo.AlignShift,0
|
|
|
|
je short no_shift ;flags set by sub above
|
|
jg short @F
|
|
or ecx,LEFT_SHIFT_NEEDED ;shl required
|
|
neg sDfbInfo.AlignShift ;take absolute value
|
|
@@:
|
|
or ecx,SOME_SHIFT_NEEDED ;shl or shr required
|
|
|
|
no_shift:
|
|
mov edx,dfb_pfnScanHandlers[ecx*4] ;proper drawing handler
|
|
mov pfnDrawScans,edx
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up the offsets to the next source and destination scans.
|
|
;
|
|
; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,[esi].xLeft
|
|
shr eax,4 ;index of first word (including partial)
|
|
mov edx,[esi].xRight
|
|
add edx,1111b
|
|
shr edx,4 ;index following last word
|
|
sub edx,eax ;# of words across dest rectangle
|
|
add edx,edx ;# of bytes across dest rectangle
|
|
mov eax,[edi].dsurf_lNextPlane ;# of bytes across 1 scan of dest
|
|
sub eax,edx ;offset from last byte dest copied to on one
|
|
mov ecx,pdsurfSrc
|
|
mov sDfbInfo.DstDelta,eax ; scan to first dest byte copied to on next
|
|
|
|
;
|
|
; use # bytes across dst rect to calculate ulSrcDelta
|
|
; the src ptr is incremented at the same time as the
|
|
; dst ptr
|
|
;
|
|
|
|
mov eax,[ecx].dsurf_lNextPlane
|
|
sub eax,edx ;offset from end of one src scan to
|
|
mov sDfbInfo.SrcDelta,eax ; start of next
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; At this point, ESI = prclDst, EDI = pdsurfDst
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,[esi].yTop ;top scan of copy
|
|
imul eax,[edi].dsurf_lNextScan ;offset of starting scan line
|
|
mov edx,[esi].xLeft ;left dest X coordinate
|
|
shr edx,3 ;left dest byte offset in row
|
|
and edx,not 1 ;round down to word ptr
|
|
add eax,edx ;initial offset in dest bitmap
|
|
add eax,[edi].dsurf_pvBitmapStart ;initial dest bitmap address
|
|
add pDst,eax ;remember where to start drawing
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; At this point, EDI->pdsurfDst
|
|
;-----------------------------------------------------------------------;
|
|
|
|
; Calculate the # of scans to do
|
|
|
|
mov ebx,[esi].yBottom ;bottom of destination rectangle
|
|
sub ebx,[esi].yTop ;# of scans to copy
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Copy to the screen in bursts of ulPlaneScans scans.
|
|
;
|
|
; At this point, EBX = # of scans remaining.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
dfb2dfb_proceed_with_copy::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Copy the DFB scans
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov esi,pSrc
|
|
mov edi,pDst
|
|
|
|
shl ebx,2
|
|
mov sDfbInfo.BurstCountLeft,ebx
|
|
mov eax,pfnDrawScans
|
|
push ebp ;-----------------------------------
|
|
lea ebp,sDfbInfo ;WARNING:
|
|
call eax ;ebp in use, pfnDrawScans is invalid
|
|
pop ebp ;-----------------------------------
|
|
|
|
cRet vDFB2DFB ;done!
|
|
|
|
endProc vDFB2DFB
|
|
|
|
|
|
|
|
public dfb2dfb_detect_partials
|
|
public dfb2dfb_one_partial_only
|
|
public dfb2dfb_check_whole_words
|
|
public dfb2dfb_set_copy_control_flags
|
|
public dfb2dfb_proceed_with_copy
|
|
|
|
_TEXT$01 ends
|
|
|
|
end
|