;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = PELSUP.ASM
;*
;* DESCRIPTIVE NAME = Pel Functions
;*
;*
;* VERSION      V2.0
;*
;* DATE         06/09/87
;*
;* DESCRIPTION  Routines relating to Pel Support
;*
;* FUNCTIONS    convert_screen_world
;*              convert_page_device
;*              convert_screen_screen
;*              convert_device_screen
;*              convert_world_screen
;*              convert_space_screen
;*              convert_space_space
;*              GetPel
;*              SetPel
;*              local_pt_visible
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   06/09/87                     Written by Walt Moore
;*   07/27/87                     Hock Lee [hockl] Modified for new DDI.
;*   07/30/87                     Hock Lee [hockl] Optimized it.
;*   10/05/87                     Hock Lee [hockl] Wrote to include other spaces
;*                                to screen.
;*   02/14/88                     Charles Whitmer [chuckwh] Made it not hit a
;*                                FIREWALL if the transfrm overflows in the Engine.
;*                                Made it add negative DC origins correctly.  Added
;*                                the checks that the SCREEN coordinates fit in 16
;*                                bits.  Added the SCREEN to SCREEN conversion
;*                                entry point so that people without COM_TRANSFORM
;*                                set can still get their coordinates checked.
;*                                Changed over to the convention that the ERROR
;*                                code is logged here, rather than by the caller.
;*                                Started calling this part directly with AL set,
;*                                rather than always falling through from above.
;*   03/01/88                     Walt Moore [waltm] Added device to screen to
;*                                add in the dc origin and check 16 bit numbers.
;*   06/05/88                     Walt Moore [waltm] Changed to call
;*                                InnerAccumulate bounds.  Was doing correlation on
;*                                unclipped primitives.
;*   11/05/91                     Cliff Levesque [cliffl] Cleanup and convert to
;*                                386 and above flat model, protected mode
;*                                32 bit operation.
;*   11/26/92                     John Batty. Added DCAF changes.
;*
;*****************************************************************************/

        .386

        .xlist

INCL_GRE_BITMAPS        equ     1
INCL_GRE_CLIP           equ     1
INCL_GRE_XFORMS         equ     1
INCL_GRE_DEVSUPPORT     equ     1
INCL_GRE_DEVMISC3       equ     1
INCL_DEV                equ     1
INCL_DDICOMFLAGS        equ     1
INCL_GPITRANSFORMS      equ     1
INCL_GPIERRORS          equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1

        include pmgre.inc
        include driver.inc
        include extern.inc
        include protos.inc
        include tune.inc
        .list

        .MODEL FLAT

        ASSUME  CS:FLAT,SS:FLAT,DS:FLAT,ES:FLAT

        .DATA

        .CODE

page
_TUNE SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = convert_screen_world
;*
;* DESCRIPTION   = this function sets up a call to the Engine for transforming
;*                 coordinates from screen coordinates to world coordinates and
;*                 then invokes the transform code.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX
;*
;* INPUT         = ECX:EDX = long pointer to the points
;*                 EBX     = count of points
;*                 ESI     = ddc
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX     = 1 (return code from Convert routine)
;* RETURN-ERROR  = EAX     = 0 (return code from Convert routine)
;*
;**************************************************************************/

ALIGN 4
convert_screen_world PROC SYSCALL USES edi,
        lpPoints:DWORD,
        dwCount:DWORD

        ddc?    esi

        mov     edi,lpPoints

;/*
;** Check for a count of zero
;*/

        mov     ecx,dwCount
        jecxz   device_to_world         ; to be sure we have right return code

;/*
;** convert from screen to device coordinates first
;*/

        ASSUME  esi:PTR DDC

        mov     ebx,[esi].ddc_prddc

        ASSUME  ebx:PTR RDDC

        rddc?   ebx

        mov     eax,[ebx].rddc_ptsOrg.ptl_x
        mov     edx,[ebx].rddc_ptsOrg.ptl_y

convert_loop:

        ASSUME  edi:PTR POINTL

        sub     [edi].ptl_x,eax
        sub     [edi].ptl_y,edx
        add     edi,size POINTL
        loop    convert_loop

device_to_world:
        mov     eax,1                                   ; assume success
        test    [esi].ddc_fb,DDC_UNIT_XFORM             ; unit transform?
        jnz     convert_done                            ;   yes
        dec     eax                                     ;A handy zero

        INVOKE  PFNDefConvert PTR pfnDefConvert,
                [esi].ddc_hdc,
                CVTC_DEVICE,
                CVTC_WORLD,
                lpPoints,
                dwCount,
                0,
                NGreConvert

convert_done:
        RET
convert_screen_world ENDP
_TUNE ENDS
_TUNE2 SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = convert_page_device
;*
;* DESCRIPTION   = Converts the given points from whatever space they are in to
;*                 SCREEN coordinates.  Calls the Engine (if necessary) to convert
;*                 as far as DEVICE, adds in the DC origin, and then checks that
;*                 the results fit in 16 bits.
;*                 These guys really just set AL to the proper source coordinate and
;*                 fall through to InnerConvertSpaceSpace to do the work.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX
;*
;* INPUT         = ESI = DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1
;* RETURN-ERROR  = EAX = 0 (Error code logged)
;*
;**************************************************************************/

ALIGN 4
convert_page_device PROC SYSCALL,
        pptl:DWORD,
        cptl:DWORD

        mov     eax,CVTC_PAGE           ; Page/Device Transform
        mov     ebx,CVTC_DEVICE

        jmp     InnerConvertSpaceSpace
ALIGN 4
convert_page_device ENDP
_TUNE2 ENDS
;/***************************************************************************
;*
;* FUNCTION NAME = convert_screen_screen
;*
;* DESCRIPTION   = Converts the given points from whatever space they are in to
;*                 SCREEN coordinates.  Calls the Engine (if necessary) to convert
;*                 as far as DEVICE, adds in the DC origin, and then checks that
;*                 the results fit in 16 bits.
;*                 These guys really just set AL to the proper source coordinate and
;*                 fall through to InnerConvertSpaceSpace to do the work.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX
;*
;* INPUT         = ESI = DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1
;* RETURN-ERROR  = EAX = 0 (Error code logged)
;*
;**************************************************************************/

ALIGN 4
convert_screen_screen PROC SYSCALL,
        pptl:DWORD,
        cptl:DWORD

        mov     eax,CVTC_SCREEN         ; Screen/Screen Transform
        mov     ebx,CVTC_SCREEN

        jmp     InnerConvertSpaceSpace
ALIGN 4

convert_screen_screen ENDP
_TUNE2 SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = convert_device_screen
;*
;* DESCRIPTION   = Converts the given points from whatever space they are in to
;*                 SCREEN coordinates.  Calls the Engine (if necessary) to convert
;*                 as far as DEVICE, adds in the DC origin, and then checks that
;*                 the results fit in 16 bits.
;*                 These guys really just set AL to the proper source coordinate and
;*                 fall through to InnerConvertSpaceSpace to do the work.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX
;*
;* INPUT         = ESI = DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1
;* RETURN-ERROR  = EAX = 0 (Error code logged)
;*
;**************************************************************************/

ALIGN 4
convert_device_screen PROC SYSCALL,
        pptl:DWORD,
        cptl:DWORD

        mov     eax,CVTC_DEVICE         ; Device/Screen Transform
        mov     ebx,CVTC_SCREEN
        jmp     InnerConvertSpaceSpace
ALIGN 4

convert_device_screen ENDP
_TUNE2 ENDS
_TUNE SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = convert_world_screen
;*
;* DESCRIPTION   = Converts the given points from whatever space they are in to
;*                 SCREEN coordinates.  Calls the Engine (if necessary) to convert
;*                 as far as DEVICE, adds in the DC origin, and then checks that
;*                 the results fit in 16 bits.
;*                 These guys really just set AL to the proper source coordinate and
;*                 fall through to InnerConvertSpaceSpace to do the work.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX
;*
;* INPUT         = ESI = DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1
;* RETURN-ERROR  = EAX = 0 (Error code logged)
;*
;**************************************************************************/

ALIGN 4
convert_world_screen PROC SYSCALL,
        pptl:DWORD,
        cptl:DWORD

        mov     eax,CVTC_WORLD          ; World/Screen Transform
        mov     ebx,CVTC_SCREEN
        jmp     InnerConvertSpaceSpace
ALIGN 4

convert_world_screen ENDP
_TUNE ENDS
;/***************************************************************************
;*
;* FUNCTION NAME = convert_space_screen_screen
;*
;* DESCRIPTION   = Converts the given points from whatever space they are in to
;*                 SCREEN coordinates.  Calls the Engine (if necessary) to convert
;*                 as far as DEVICE, adds in the DC origin, and then checks that
;*                 the results fit in 16 bits.
;*                 These guys really just set AL to the proper source coordinate and
;*                 fall through to InnerConvertSpaceSpace to do the work.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX
;*
;* INPUT         = ESI = DDC
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1
;* RETURN-ERROR  = EAX = 0 (Error code logged)
;*
;**************************************************************************/

ALIGN 4
convert_space_screen PROC SYSCALL,
        pptl:DWORD,
        cptl:DWORD

        mov     ebx,CVTC_SCREEN
        jmp     InnerConvertSpaceSpace
ALIGN 4

convert_space_screen ENDP
_TUNE SEGMENT DWORD FLAT PUBLIC 'CODE'
;/***************************************************************************
;*
;* FUNCTION NAME = convert_space_space
;*
;* DESCRIPTION   = Converts the given points from whatever space they are in to
;*                 SCREEN coordinates.  Calls the Engine (if necessary) to convert
;*                 as far as DEVICE, adds in the DC origin, and then checks that
;*                 the results fit in 16 bits.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EBX,EDX
;*
;* INPUT         = ESI = DDC
;*                 EAX = Source coordinate space
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1
;*                 ECX = 1
;* RETURN-ERROR  = EAX = 0 (Error code logged)
;*                 ECX = 0
;**************************************************************************/
ALIGN 4
convert_space_space PROC SYSCALL,
        pptl:DWORD,
        cptl:DWORD

InnerConvertSpaceSpace::

        push    edi

        ddc?    esi

        mov     edi,ebx                 ; DX:BX = Target space (screen/device)
        mov     ecx,cptl
        jecxz   transform_done_ok

;/*
;** if we're told to do SCREEN to SCREEN, then just check the coordinates
;*/

        cmp     eax,CVTC_DEVICE
        ja      just_check_16_bits      ;Must be screen to screen
        je      we_got_device           ;Device to screen, do DC origin

;/*
;** call the Engine to convert to DEVICE coordinates, if it's non-trivial
;*/

        cmp     eax,CVTC_WORLD          ; no short cut if source is not world
        jnz     call_convert
        test    [esi].ddc_fb,DDC_UNIT_XFORM
        jnz     we_got_device

call_convert:

        INVOKE  PFNDefConvert PTR pfnDefConvert,
                [esi].ddc_hdc,
                eax,
                CVTC_DEVICE,
                pptl,
                ecx,
                0,
                NGreConvert

        or      eax,eax
        jz      convert_space_space_exit

we_got_device:

;/*
;** add in the DC origin
;*/

        cmp     edi,CVTC_DEVICE
        jz      just_check_16_bits      ; target space is device
        mov     edi,pptl
        mov     ecx,cptl

        mov     ebx,[esi].ddc_prddc

        rddc?   ebx

        mov     eax,[ebx].rddc_ptsOrg.ptl_x
        mov     edx,[ebx].rddc_ptsOrg.ptl_y


dc_origin_loop:

        add     [edi].ptl_x,eax
        add     [edi].ptl_y,edx
        add     edi,SIZE POINTL
        loop    dc_origin_loop

;/*
;** check the results to see if they fit in 16 bits
;*/

just_check_16_bits:

check_16_bits:

        mov     edi,pptl
        mov     ecx,cptl
        add     ecx,ecx                 ; CX = count of DWORDS

check_16_loop:

        movsx   eax,WORD PTR[edi]
        cmp     eax,DWORD PTR [edi]
        jnz     convert_space_error
        add     edi,4
        loop    check_16_loop

transform_done_ok:

        mov     eax,1                   ; indicate success
        jmp     convert_space_space_exit
ALIGN 4

;/*
;** handle errors
;*/

convert_space_error:

        mov     eax,PMERR_COORDINATE_OVERFLOW

        save_error_code

        xor     eax,eax

convert_space_space_exit:
        mov     ecx,eax
        pop     edi
        RET
convert_space_space ENDP
_TUNE ENDS
page

;/***************************************************************************
;*
;* FUNCTION NAME = GetPel
;*
;* DESCRIPTION   = This function returns the color index (or RGB triplet) of the
;*                 given pel.  The pel's coordinate must be clipped against the
;*                 bounds of the device to avoid an addressing exception (this
;*                 can be accomplished by checking if the point is visible).
;*                 This function only recognizes the COM_TRANSFORM bit of the
;*                 command. dword.  Any other bit will be ignored.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX,FLAGS
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EDX:EAX = pel color
;* RETURN-ERROR  = EAX = -1
;*
;**************************************************************************/

ALIGN 4
GetPel  PROC SYSCALL USES EBX edi esi,
                     hdc:DWORD,
                     lpParm:DWORD,
                     hddc:DWORD,
                     FunN:DWORD

        LOCAL   a_point:POINTL

        DebugMsg<GetPel, DISPATCH, pelsup, CLIFFL>

        ddc?    hddc,<SURFACE>

        cld
        mov     esi,hddc
        mov     edx,esi
        ENTER_DRIVER2
        mov     eax,-1                  ; assume error
        jc      gp_exit_no_lock

        ASSUME  esi:PTR DDC

        mov     edi,FunN
        test    [esi].ddc_fbAbove,DDC_INFO_DC
        jnz     get_pel_ic
        mov     al,[esi].ddc_fb
        test    al,DDC_PRESENT
        jz      get_pel_bitmap_error
        test    al,DDC_VISIBLE          ; This test will catch null clip
        jz      get_pel_clipped_error   ;   or an IC


;/*
;** Make sure the system color info is up to date.  We do this just incase
;** the color of the returned pel maps to one of the system colors of a
;** logical color table.
;*/

        mov     eax,[esi].ddc_iSysClr
        cmp     eax,ddcInit.ddc_iSysClr

        je      get_pel_sys_colors_good

        INVOKE  PropagateSysClrChange

        jmp     get_pel_sys_colors_good
ALIGN 4

;/*
;** A few error handlers here in the middle of nowhere.  Sys colors should
;** not change much, so this should be a good place for them.
;*/

get_pel_ic:

        mov     eax,PMERR_PEL_NOT_AVAILABLE
        jmp     get_pel_log_error
ALIGN 4

get_pel_clipped_error:

        mov     eax,PMERR_PEL_IS_CLIPPED
        jmp     get_pel_log_error
ALIGN 4

get_pel_bitmap_error:

        mov     eax,PMERR_BITMAP_NOT_SELECTED

get_pel_log_error:

        save_error_code

get_pel_error_exit:

        mov     eax,-1
        jmp     get_pel_exit
ALIGN 4

;/*
;** The colors and surface are valid.  Transform the coordinate if needed.
;** The convert function will be called even if the transform bit isn't
;** set because it will validate the coordinates for us.
;*/

get_pel_sys_colors_good:

        mov     ebx,lpParm              ;In protected mode, it will be
        mov     eax,DWORD PTR [ebx]             ;  to pay the cost of the segment
        mov     a_point.ptl_x,eax       ;  loads for a movsw
        mov     eax,DWORD PTR [ebx][4]
        mov     a_point.ptl_y,eax

        .errnz  POINTL.ptl_x
        .errnz  POINTL.ptl_y-POINTL.ptl_x-4

        mov     eax,CVTC_SCREEN
        test    edi,COM_TRANSFORM
        jz      @F                      ;No transforming, just range check
        mov     eax,CVTC_WORLD
@@:
;           4-06-92
;
        lea     ebx,a_point
        INVOKE  convert_space_screen, ebx, 1

        or      eax,eax
        jz      get_pel_error_exit

;/*
;** See if the point is visible.  If so, then we can get it, else we
;** will returned the clipped error code.
;*/

        lea     ebx,a_point             ;SS:BX --> point
        call    local_pt_visible        ;DS:SI --> hddc
        or      eax,eax
        jz      get_pel_clipped_error   ;Point isn't visible
        mov     ebx,[esi].ddc_npsd

        ASSUME  ebx:PTR SURFACE

        mov     ecx,a_point.ptl_y       ;Flip the coordinate system.
        sub     ecx,[ebx].sd_cy
        not     ecx                     ;AX = garbage for the call

        INVOKE  Pixel, a_point.ptl_x, ecx, eax, -1      ;Expects ESI = hddc


get_pel_exit:
get_pel_exitx:

        call    leave_driver

gp_exit_no_lock:

        fw_zero <ecx>

        RET

GetPel  ENDP

page

;/***************************************************************************
;*
;* FUNCTION NAME = SetPel
;*
;* DESCRIPTION   = The pel at the given location is set using the current line
;*                 attribute's color and mix.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX,FLAGS
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 1
;* RETURN-ERROR  = EAX = 0
;*
;**************************************************************************/

ALIGN 4
SetPel  PROC SYSCALL USES EBX edi esi,      hdc:DWORD, lpParm:DWORD, hddc:DWORD,
                                        FunN:DWORD
        LOCAL   a_point:POINTL
ifdef DCAF                                                           ;          
        LOCAL   fpt_visible:DWORD     ; return value from pt_visible ;          
endif ; DCAF                                                         ;          


        DebugMsg<SetPel, pelsup, CLIFFL>

        ddc?    hddc,<SURFACE>

        cld
        mov     esi,hddc
        mov     edx,esi
        ENTER_DRIVER2
        jc      sp_exit_no_lock         ; DX:AX = 0 on error

;/*
;** This function is not valid in a path or area, and a bitmap must be
;** selected into the ddc.
;*/

        ASSUME  esi:PTR DDC

        mov     edi,FunN
        test    edi,COM_PATH OR COM_AREA
        jnz     set_pel_path_area_error
        test    [esi].ddc_fb,DDC_PRESENT
        jz      set_pel_bitmap_error

;/*
;** Make sure the system color info and line colors are up to date.
;*/

        mov     eax,[esi].ddc_iSysClr
        cmp     eax,ddcInit.ddc_iSysClr

        jne     set_pel_need_sys_colors
        test    [esi].ddc_la.la_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV
        jz      set_pel_colors_ok
        jmp     set_pel_need_colors
ALIGN 4

set_pel_need_sys_colors:

        INVOKE  PropagateSysClrChange

set_pel_need_colors:

        lea     ebx,[esi].ddc_la.la_ba
        call    MakeColorsValid
        jns     set_pel_colors_ok
        jmp     set_pel_error_exit
ALIGN 4

;/*
;** A few error handlers here in the middle of nowhere.  Sys colors should
;** not change much, so this should be a good place for them.
;*/

set_pel_bitmap_error:

        mov     eax,PMERR_BITMAP_NOT_SELECTED
        jmp     set_pel_log_error
ALIGN 4

set_pel_path_area_error:

        mov     eax,PMERR_INV_IN_AREA
        test    edi,COM_AREA
        jnz     set_pel_log_error
        mov     eax,PMERR_INV_IN_PATH

set_pel_log_error:

        save_error_code

set_pel_error_exit:

        xor     eax,eax
        jmp     set_pel_exit
ALIGN 4

;/*
;** The colors and surface are valid.  Transform the coordinate if needed.
;** The convert function will be called even if the transform bit isn't
;** set because it will validate the coordinates for us.
;*/

set_pel_colors_ok:

        mov     ebx,esi
        mov     esi,lpParm              ;In protected mode, it will be
        mov     eax,DWORD PTR [esi]             ;  to pay the cost of the segment
        mov     a_point.ptl_x,eax       ;  loads for a movsw
        mov     eax,DWORD PTR [esi][4]
        mov     a_point.ptl_y,eax
        mov     esi,ebx

        .errnz  POINTL.ptl_x
        .errnz  POINTL.ptl_y-POINTL.ptl_x-4

        mov     eax,CVTC_SCREEN
        test    edi,COM_TRANSFORM
        jz      @F                      ;No transforming, just range check
        mov     eax,CVTC_WORLD
@@:
        lea     ebx,a_point
        INVOKE  convert_space_screen, ebx, 1

        or      eax,eax
        jz      set_pel_exit

;/*
;** Perform any bounds accumulation which needs to be performed.  We call
;** our own InnerAccumulateBounds function for this.  It takes an inclusive
;** rectangle in screen coordinates
;*/

ifdef DCAF                                                           ;          
;/*                                                                  ;          
;** If we are asked to accumulate SCREEN bounds, then we only        ;          
;** want to do so if the point is visible                            ;          
;*/                                                                  ;          
        test    edi, COM_SCR_BOUND                                   ;          
        jz      screen_bit_tested                                    ;          
                                                                     ;          
        lea     ebx,a_point             ;EBX -> point                ;          
        call    local_pt_visible        ;ESI -> hddc                 ;          
        mov     fpt_visible,eax         ;Save this result for later  ;          
        or      eax,eax                                              ;          
        jnz     screen_bit_tested       ;Point is visible            ;          
                                                                     ;          
;/*                                                                  ;          
;** Turn off the SCREEN bound accumulation as the point is invisible ;          
;*/                                                                  ;          
        and     edi, NOT COM_SCR_BOUND                               ;          
                                                                     ;          
screen_bit_tested:                                                   ;          
        test    edi,COM_BOUND+COM_ALT_BOUND+COM_SCR_BOUND            ;          
                                                                     ;          
else  ; DCAF                                                         ;          
        test    edi,COM_BOUND+COM_ALT_BOUND
endif ; DCAF                                                         ;          

        jz      set_pel_bounds_done
        mov     eax,a_point.ptl_x       ;(EAX) = left lower corner
        mov     ebx,a_point.ptl_y
        mov     ecx,eax                 ;(CX:DX) = right upper corner
        mov     edx,ebx
        call    InnerAccumulateBounds   ;DS:SI --> ddc, DI = Command flags
        or      eax,eax
        jz      set_pel_exit            ;Some error occured

set_pel_bounds_done:

;/*
;** See if the point is visible.  If so, then we'll have to possibly
;** draw it and perform correlation on it.
;*/

ifdef DCAF                                                           ;          
;/*                                                                  ;          
;** The point will have already been tested for visibility if        ;          
;** the COM_SCR_BOUND is set, and the return value is then in        ;          
;** fpt_visible.                                                     ;          
;*/                                                                  ;          
        mov     eax, fpt_visible        ;get the (potential) saved result ;          
        test    FunN, COM_SCR_BOUND     ;only valid if this bit set  ;          
        jnz     already_tested                                       ;          
endif ; DCAF                                                         ;          
        lea     ebx,a_point             ;SS:BX --> point
        call    local_pt_visible        ;DS:SI --> hddc
ifdef DCAF                                                           ;          
already_tested:                                                      ;          
endif ; DCAF                                                         ;          
        or      eax,eax
        mov     eax,1
        jz      set_pel_exit            ;Point isn't visible
        and     al,[esi].ddc_fb
        shl     eax,16  ;SEL ADDED 5/6/92
        and     eax,edi


        .errnz  DDC_VISIBLE - COM_DRAW SHR 16
        .errnz  DDC_VISIBLE-1

        jz      set_pel_drawn           ;No draw bit, can't draw it
        mov     ebx,[esi].ddc_npsd
        ASSUME  ebx:PTR SURFACE
        mov     ecx,a_point.ptl_y       ;Flip the coordinate system.
        sub     ecx,[ebx].sd_cy
        not     ecx
        movzx   eax,[esi].ddc_la.la_ba.ba_ipc.ipc_bClr
        mov     bl,[esi].ddc_la.la_ba.ba_bmix
        movzx   ebx,bl

        INVOKE  Pixel, a_point.ptl_x, ecx, eax, ebx    ;Expects ESI = hddc

set_pel_drawn:

;/*
;** The pel has been drawn.  If correlation is to be performed, then call
;** the correlation routine.
;*/

        mov     eax,1
        test    edi,COM_CORRELATE
        jz      set_pel_exit            ;No correlation needed
        mov     ebx,a_point.ptl_x
        mov     edx,a_point.ptl_y
        call    correlate_for_point_si  ;Return code of 1 or 2

set_pel_exit:

        call    leave_driver

sp_exit_no_lock:

        fw_zero <ecx>

        RET

SetPel  ENDP

page

;/***************************************************************************
;*
;* FUNCTION NAME = local_pt_visible
;*
;* DESCRIPTION   = This function sets up for a call to the Engine for checking if
;*                 the given point is visible.  The point has already been
;*                 transformed into screen coordinates.
;*
;*                 Registers Preserved:
;*                       ESI,EDI,EBP
;*                 Registers Destroyed:
;*                       EAX,EBX,ECX,EDX,FLAGS
;*
;* INPUT         = ESI = hddc
;*                 EBX = long pointer to the point
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = EAX = 0  if not visible
;*                     = 1  if visible
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
local_pt_visible        PROC SYSCALL


        DebugMsg<local_pt_visible, pelsup, CLIFFL>

        ddc?    esi

;/*
;** If there is just a single clipping rectangle, we will perform the
;** hit test ourselves.  If there are more, then we will let the default
;** handler do it.
;*/

        mov     eax,1

        ASSUME  esi:PTR DDC

        cmp     [esi].ddc_crcsClip,eax
        jl      local_pt_vis_exit       ;No clip rectangles, make ax = 0
        jg      engine_pt_visible       ;More than one, use engine

;/*
;** Perform our own point visible function.
;*/

        mov     esi,[esi].ddc_prddc     ; ESI = RDDC

        ASSUME  esi:PTR RDDC,ebx:PTR POINTL

        mov     edx,[ebx].ptl_x
        cmp     edx,[esi].rddc_arcsClip.rcl_xLeft
        jl      local_pt_vis_exit       ;Left edge inclusive in screen coords
        cmp     edx,[esi].rddc_arcsClip.rcl_xRight
        jge     local_pt_vis_exit       ;Right edge exclusive
        mov     edx,[ebx].ptl_y
        cmp     edx,[esi].rddc_arcsClip.rcl_yBottom
        jl      local_pt_vis_exit       ;Bottom edge inclusive
        cmp     edx,[esi].rddc_arcsClip.rcl_yTop
        jge     local_pt_vis_exit       ;Top edge exclusive
        inc     eax                     ;Want to return 1 to show visible
        mov     esi,[esi].rddc_npddc    ; SI = DDC

        ASSUME  esi:PTR DDC

        ddc?    esi

        jmp     local_pt_vis_exit
ALIGN 4

engine_pt_visible:

        INVOKE  PFNDefPtVisible PTR pfnDefPtVisible,
                [esi].ddc_hdc,
                ebx,
                0,
                NGrePtVisible

local_pt_vis_exit:

        dec     eax

ifdef FIREWALLS

;/*
;** The only way an error could be returned is if we screwed up or
;** somebody else screwed up.  The coordinates are in screen coordinates,
;** so they cannot give me an error.  Anything else I can think of
;** would be a logic error which would need to be caught and fixed.
;*/

        jns     no_ptvisible_error

        rip     text,<Error returned by PtVisible>

no_ptvisible_error:

endif

                        RET

local_pt_visible        ENDP

end
