471 lines
18 KiB
NASM
471 lines
18 KiB
NASM
;---------------------------Module-Header------------------------------;
|
|
;
|
|
; Module Name: dfb2dib.asm
|
|
;
|
|
; Copyright (c) 1993 Microsoft Corporation
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; VOID vDFB2DIB(DEVSURF * pdsurfDst,
|
|
; DEVSURF * pdsurfSrc,
|
|
; RECTL * prclDst,
|
|
; POINTL * pptlSrc);
|
|
;
|
|
; Performs accelerated copies from a DFB to a DIB.
|
|
;
|
|
; pdsurfDst = pointer to dest surface
|
|
; pdsurfSrc = pointer to source surface
|
|
; prclDst = pointer to rectangle describing target area of dest. DIB
|
|
; 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.
|
|
;
|
|
; This routine uses a 2K buffer on the stack
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.486
|
|
|
|
.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
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Masks to be applied to the source data for the 8 possible clip
|
|
; alignments.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
dfb2dib_jLeftMasks label byte
|
|
db 0ffh, 00fh
|
|
|
|
dfb2dib_jRightMasks label byte
|
|
db 0ffh, 0f0h
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Translate table used to spread out a nibble to a WORD, with three
|
|
; blank spacer bits between each actual bit.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
aXlate label dword
|
|
dd 0000h,0800h,8000h,8800h,0008h,0808h,8008h,8808h
|
|
dd 0080h,0880h,8080h,8880h,0088h,0888h,8088h,8888h
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Array of function pointers to handle leading and trailing bytes
|
|
;-----------------------------------------------------------------------;
|
|
pfnScanhandlers label dword
|
|
dd draw_dfb2dib_scan_00
|
|
dd draw_dfb2dib_scan_01
|
|
dd draw_dfb2dib_scan_10
|
|
dd draw_dfb2dib_scan_11
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.code
|
|
|
|
_TEXT$01 SEGMENT DWORD USE32 PUBLIC 'CODE'
|
|
ASSUME DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc vDFB2DIB,16,< \
|
|
uses esi edi ebx, \
|
|
pdsurfDst: ptr DEVSURF, \
|
|
pdsurfSrc: ptr DEVSURF, \
|
|
prclDst: ptr RECTL, \
|
|
pptlSrc : ptr POINTL >
|
|
|
|
local ulSrcBytesWide:dword ;src copy width (paritials included)
|
|
local ulDstBytesWide:dword ;dst copy width (paritials included)
|
|
local ulSrcBytesPerPlane:dword ;# of bytes in a src scan line
|
|
local ulDstBytesPerScan:dword ;# of bytes in a dst scan line
|
|
local ulSrcDelta:dword ;from end of src scan to start of next
|
|
local ulDstDelta:dword ;from end of dst scan to start of next
|
|
local pSrc:dword ;ptr to drawing src start
|
|
local pDst:dword ;ptr to drawing dst start
|
|
local pBuf:dword ;ptr to temp dst start (conversion buf)
|
|
local pfnCopy:dword ;ptr to temp => DIB copy function
|
|
local ulSrcIntraByte:dword ;src intra-byte index
|
|
local ulAlignShift:dword
|
|
local ulLeftMask:dword
|
|
local ulRightMask:dword
|
|
local ulThreePlanes:dword
|
|
local ulWidthInPixels:dword
|
|
local ulNumScans:dword
|
|
local ulNumScansLeft:dword
|
|
local ulLowWord:dword
|
|
local ulLastDword:dword
|
|
local aTempBuf[(MAX_SCAN_WIDTH/2)+16]:byte
|
|
;we need enough space to store the scan
|
|
; plus up to four dwords
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cld
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Point to the source start address (nearest dword equal or less).
|
|
;-----------------------------------------------------------------------;
|
|
|
|
begin_setup::
|
|
|
|
mov ebx,pptlSrc ;point to coords of source upper left
|
|
mov edx,prclDst ;point to rectangle to which to copy
|
|
mov esi,pdsurfSrc ;point to surface to copy from (DFB4)
|
|
mov edi,pdsurfDst ;point to surface to copy to (DIB4)
|
|
|
|
mov eax,[edi].dsurf_lNextScan
|
|
mov ulDstBytesPerScan,eax ;set dest scan width
|
|
mov eax,[esi].dsurf_lNextPlane
|
|
mov ulSrcBytesPerPlane,eax ;set source scan width
|
|
|
|
lea eax,[eax+2*eax]
|
|
mov ulThreePlanes,eax ;ulThreePlanes = 3 * source scan width
|
|
|
|
mov eax,[ebx].ptl_y
|
|
imul eax,[esi].dsurf_lNextScan ;offset in bitmap of top src rect scan
|
|
mov ecx,[ebx].ptl_x
|
|
shr ecx,3 ;source byte X address
|
|
add eax,ecx ;offset in bitmap of first source byte
|
|
add eax,[esi].dsurf_pvBitmapStart ;pointer to first source dword
|
|
mov pSrc,eax
|
|
|
|
mov eax,[edx].yTop
|
|
imul eax,ulDstBytesPerScan ;offset in bitmap of top dst rect scan
|
|
mov ecx,[edx].xLeft
|
|
shr ecx,1 ;dest byte X address
|
|
add eax,ecx ;offset in bitmap of first source dword
|
|
add eax,[edi].dsurf_pvBitmapStart ;pointer to first source dword
|
|
mov pDst,eax
|
|
|
|
mov eax,[edx].xRight
|
|
sub eax,[edx].xLeft
|
|
mov ulWidthInPixels,eax ;save width in pixels
|
|
|
|
mov eax,[ebx].ptl_x ;calculate src right
|
|
add eax,ulWidthInPixels ;src right
|
|
add eax,111b
|
|
shr eax,3 ;src right rounded up to byte
|
|
mov ecx,[ebx].ptl_x ;src left edge
|
|
shr ecx,3 ;src left rounded down to whole byte
|
|
sub eax,ecx
|
|
|
|
inc eax ;convert one extra byte in case we
|
|
; require a shift
|
|
|
|
mov ulSrcBytesWide,eax ;# of bytes in src touched by copy
|
|
|
|
mov eax,[edx].xRight
|
|
inc eax
|
|
shr eax,1 ;dst right rounded up to whole byte
|
|
mov ecx,[edx].xLeft
|
|
shr ecx,1 ;dst left rounded down to whole byte
|
|
sub eax,ecx
|
|
mov ulDstBytesWide,eax ;# of bytes in dst touched by copy
|
|
|
|
mov eax,ulSrcBytesPerPlane
|
|
shl eax,2
|
|
sub eax,ulSrcBytesWide
|
|
mov ulSrcDelta,eax
|
|
|
|
mov eax,ulDstBytesPerScan
|
|
sub eax,ulDstBytesWide
|
|
mov ulDstDelta,eax
|
|
|
|
mov eax,[edx].xLeft ;get dst left edge
|
|
and eax,1b ;0 - byte aligned, 1 - not byte aligned
|
|
mov cl,dfb2dib_jLeftMasks[eax] ;look up dst left mask
|
|
mov ch,cl ;store mask in cl
|
|
not ch ;store not mask in ch
|
|
mov ulLeftMask,ecx ;save dst left mask
|
|
|
|
mov eax,[edx].xRight ;get dst right edge
|
|
and eax,1b ;0 - byte aligned, 1 - not byte aligned
|
|
mov cl,dfb2dib_jRightMasks[eax] ;look up dst right mask
|
|
mov ch,cl ;store mask in cl
|
|
not ch ;store not mask in ch
|
|
mov ulRightMask,ecx ;save dst right mask
|
|
|
|
mov ecx,[edx].xLeft ;get left edge
|
|
and ecx,1 ;1 - left partial, 0 - none
|
|
sub ulDstBytesWide,ecx ;remove partials
|
|
shl ecx,1
|
|
mov eax,[edx].xRight ;get right edge
|
|
and eax,1 ;1 - right partial, 0 - none
|
|
sub ulDstBytesWide,eax ;remove partials
|
|
jge @F
|
|
mov ulDstBytesWide,0 ;we must have had just 1 partial
|
|
@@:
|
|
|
|
or eax,ecx
|
|
mov ecx,pfnScanhandlers[eax*4]
|
|
mov pfnCopy,ecx ;save ptr to appropriate copy function
|
|
|
|
mov eax,[edx].yBottom ;get bottom scan
|
|
mov ecx,[edx].yTop ;get top scan
|
|
sub eax,ecx
|
|
mov ulNumScans,eax ;# of scans to copy
|
|
|
|
mov eax,[ebx].ptl_x
|
|
xor eax,[edx].xLeft
|
|
and eax,1 ;eax = (0-aligned 1-nonaligned)
|
|
mov ulAlignShift,eax
|
|
|
|
mov eax,[ebx].ptl_x
|
|
and eax,111b ;calculate src intra-byte index
|
|
mov ulSrcIntraByte,eax
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; At this point, EBX = pptlSrc, EDX = prclDst,
|
|
; ESI = pdsurfSrc, EDI = pdsurfDst
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,ulNumScans
|
|
mov ulNumScansLeft,eax
|
|
|
|
lea esi,aTempBuf
|
|
mov pBuf,esi
|
|
|
|
do_scan_line::
|
|
|
|
mov ecx,ulSrcBytesWide
|
|
mov esi,pSrc
|
|
mov edi,pBuf
|
|
|
|
cmp ulAlignShift,0
|
|
je short @F
|
|
xor eax,eax
|
|
mov ulLastDword,eax
|
|
@@:
|
|
|
|
mov eax,ulSrcBytesPerPlane
|
|
|
|
convert_byte::
|
|
|
|
;------------------------------------------------------------------------
|
|
; process the high nibble of the bytes
|
|
;------------------------------------------------------------------------
|
|
|
|
mov bl,[esi] ; move plane0 byte into ebx
|
|
shr ebx,2 ; we need nibble 1 (*4)
|
|
and ebx,111100b
|
|
mov edx,aXlate[ebx] ; put plane0 data into edx
|
|
|
|
shr edx,1 ; shift edx into place
|
|
add esi,eax ; next plane
|
|
mov bl,[esi] ; move plane1 byte into ebx
|
|
shr ebx,2 ; we need nibble 1 (*4)
|
|
and ebx,111100b
|
|
or edx,aXlate[ebx] ; merge plane1 data into edx
|
|
|
|
shr edx,1 ; shift edx into place
|
|
add esi,eax ; next plane
|
|
mov bl,[esi] ; move plane2 byte into ebx
|
|
shr ebx,2 ; we need nibble 1 (*4)
|
|
and ebx,111100b
|
|
or edx,aXlate[ebx] ; merge plane2 data into edx
|
|
|
|
shr edx,1 ; shift edx into place
|
|
add esi,eax ; next plane
|
|
mov bl,[esi] ; move plane3 byte into ebx
|
|
shr ebx,2 ; we need nibble 1 (*4)
|
|
and ebx,111100b
|
|
or edx,aXlate[ebx] ; merge plane3 data into edx
|
|
|
|
sub esi,ulThreePlanes
|
|
|
|
mov ulLowWord,edx
|
|
|
|
;------------------------------------------------------------------------
|
|
; process the low nibble of the bytes
|
|
;------------------------------------------------------------------------
|
|
|
|
mov bl,[esi] ; move plane0 byte into ebx
|
|
shl ebx,2 ; we need nibble 0 (*4)
|
|
and ebx,111100b
|
|
mov edx,aXlate[ebx] ; put plane0 data into edx
|
|
|
|
shr edx,1 ; shift edx into place
|
|
add esi,eax ; next plane
|
|
mov bl,[esi] ; move plane1 byte into ebx
|
|
shl ebx,2 ; we need nibble 0 (*4)
|
|
and ebx,111100b
|
|
or edx,aXlate[ebx] ; merge plane1 data into edx
|
|
|
|
shr edx,1 ; shift edx into place
|
|
add esi,eax ; next plane
|
|
mov bl,[esi] ; move plane1 byte into ebx
|
|
shl ebx,2 ; we need nibble 0 (*4)
|
|
and ebx,111100b
|
|
or edx,aXlate[ebx] ; merge plane2 data into edx
|
|
|
|
shr edx,1 ; shift edx into place
|
|
add esi,eax ; next plane
|
|
mov bl,[esi] ; move plane1 byte into ebx
|
|
shl ebx,2 ; we need nibble 0 (*4)
|
|
and ebx,111100b
|
|
or edx,aXlate[ebx] ; merge plane3 data into edx
|
|
|
|
sub esi,ulThreePlanes
|
|
|
|
shl edx,16 ; move result to HIGH word of edx
|
|
or edx,ulLowWord
|
|
|
|
cmp ulAlignShift,0 ; byte align if needed
|
|
je short @F
|
|
mov eax,ulLastDword
|
|
bswap edx
|
|
mov ulLastDword,edx
|
|
shrd edx,eax,4
|
|
bswap edx
|
|
@@:
|
|
|
|
mov eax,ulSrcBytesPerPlane
|
|
|
|
mov [edi],edx ; store dword in target buff
|
|
add edi,4
|
|
inc esi
|
|
dec ecx ; we done one more src byte
|
|
jg convert_byte
|
|
|
|
add esi,ulSrcDelta ; advance pSrc to next scan
|
|
mov pSrc,esi
|
|
|
|
mov esi,pBuf ; copy from buf to dest DIB
|
|
mov eax,ulSrcIntraByte ; skip this many pixels
|
|
add eax,ulAlignShift ; round up if you aligned
|
|
shr eax,1 ; skip this many bytes
|
|
add esi,eax
|
|
mov edi,pDst
|
|
mov ecx,ulDstBytesWide
|
|
|
|
jmp pfnCopy
|
|
|
|
dfb2dib_done_with_copy::
|
|
|
|
add edi,ulDstDelta
|
|
mov pDst,edi
|
|
|
|
dec ulNumScansLeft
|
|
jnz do_scan_line
|
|
|
|
|
|
cRet vdfb2dib ;done!
|
|
|
|
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Copy from temp buffer to the dest. no leading byte, no trailing byte
|
|
;-----------------------------------------------------------------------;
|
|
|
|
draw_dfb2dib_scan_00::
|
|
rep movsb ;copy whole bytes
|
|
jmp dfb2dib_done_with_copy
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Copy from temp buffer to the dest. no leading byte, 1 trailing byte
|
|
;-----------------------------------------------------------------------;
|
|
|
|
draw_dfb2dib_scan_01::
|
|
rep movsb ;copy whole bytes
|
|
mov edx,ulRightMask ;load mask
|
|
mov al,[esi] ;read from temp buffer
|
|
mov bl,[edi] ;read dest byte
|
|
and al,dl ;mask src
|
|
and bl,dh ;mask dest
|
|
or al,bl ;combine src with dest
|
|
mov [edi],al ;write to dest
|
|
inc esi
|
|
inc edi
|
|
jmp dfb2dib_done_with_copy ;done with buffer
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Copy from temp buffer to the dest. 1 leading byte, no trailing byte
|
|
;-----------------------------------------------------------------------;
|
|
|
|
draw_dfb2dib_scan_10::
|
|
mov edx,ulLeftMask ;load mask
|
|
mov al,[esi] ;read from temp buffer
|
|
mov bl,[edi] ;read dest byte
|
|
and al,dl ;mask src
|
|
and bl,dh ;mask dest
|
|
or al,bl ;combine src with dest
|
|
mov [edi],al ;write to dest
|
|
inc esi
|
|
inc edi
|
|
rep movsb ;copy whole bytes
|
|
jmp dfb2dib_done_with_copy ;done with buffer
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Copy from temp buffer to the dest. 1 leading byte, 1 trailing byte
|
|
;-----------------------------------------------------------------------;
|
|
|
|
draw_dfb2dib_scan_11::
|
|
mov edx,ulLeftMask ;load mask
|
|
mov al,[esi] ;read from temp buffer
|
|
mov bl,[edi] ;read dest byte
|
|
and al,dl ;mask src
|
|
and bl,dh ;mask dest
|
|
or al,bl ;combine src with dest
|
|
mov [edi],al ;write to dest
|
|
inc esi
|
|
inc edi
|
|
rep movsb ;copy whole bytes
|
|
mov edx,ulRightMask ;load mask
|
|
mov al,[esi] ;read from temp buffer
|
|
mov bl,[edi] ;read dest byte
|
|
and al,dl ;mask src
|
|
and bl,dh ;mask dest
|
|
or al,bl ;combine src with dest
|
|
mov [edi],al ;write to dest
|
|
inc esi
|
|
inc edi
|
|
jmp dfb2dib_done_with_copy ;done with buffer
|
|
|
|
endProc vdfb2dib
|
|
|
|
|
|
|
|
public begin_setup
|
|
public do_scan_line
|
|
public convert_byte
|
|
public dfb2dib_done_with_copy
|
|
public draw_dfb2dib_scan_00
|
|
public draw_dfb2dib_scan_01
|
|
public draw_dfb2dib_scan_10
|
|
public draw_dfb2dib_scan_11
|
|
public dfb2dib_jLeftMasks
|
|
public dfb2dib_jRightMasks
|
|
|
|
|
|
_TEXT$01 ends
|
|
|
|
end
|