;*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
;-----------------------------Module-Header-----------------------------;
; Module Name:  update.asm
;
; This file contains the fast routine for update colors
;
;-----------------------------------------------------------------------;

        .386p
        .xlist

INCL_GPIBITMAPS EQU     1
include os2.inc
include eddinclt.inc
ifdef PALETTE_MGR

?df     equ     1
include cmacros.inc

include eddhmacr.inc
include eddhcone.inc
include eddhtype.inc

_DATA   segment use32 dword public 'DATA'                               ;**

ifndef  _8514
extrn _pRealXGARegs             :word
else
include 8514.inc
extrn _pReal8514Regs            :word
endif
extrn _pPhunkPhys               :dword
extrn _pPhunkVirt               :dword
extrn _DirectListEntry          :byte
extrn _UCMapping                :byte
extrn _pbHWPollRegister         :dword

_DATA   ends

_TEXT   segment dword use32 public 'CODE'                               ;**
                assume  cs:FLAT, ds:FLAT, es:FLAT

;/**********************************************************************
;/* Function:  UpdateRectangle
;/* Purpose:   Does the update colors mapping for a single rectangle
;/**********************************************************************

cProc   UpdateRectangle,<PUBLIC,NODATA>,<edi,esi>                       ;**

        parmD   pRectangle

        localW  usRectWidth
        localW  usRectHeight
        localW  usXLeft
        localW  usYBottom

cBegin
        pushxga                 ; save the segment register used for XGA

        ; process the rectangle to get the values in the form we want
        ; Note that the rectangle passed to us is in screen coords and
        ; we will use device coords. (ie 0,0 will mean top left of screen).
        mov     edi,pRectangle                                          ;**

        ; first find the width
        mov     ax, word ptr [edi].rcl_xLeft    ; get usXLeft           ;**
        mov     usXLeft, ax                     ; keep this locally
        neg     ax                              ; get (- usXLeft)
        add     ax, word ptr [edi].rcl_xRight   ; get xRight - usXLeft  ;**
        mov     usRectWidth, ax

        ; now the height
        mov     ax, word ptr [edi].rcl_yTop
        sub     ax, word ptr [edi].rcl_yBottom
        mov     usRectHeight, ax

        ; now usYBottom in our local device coords.
        mov     ax, _DirectListEntry.hw_height
        sub     ax, word ptr [edi].rcl_yBottom
        mov     usYBottom, ax

        ; wait for the real hardware to be free
        ifndef  _8514
        movxga  _pRealXGARegs
        else
        movxga  _pReal8514Regs
        endif
        waitshort

        ; select mixes for a straight copy
        memregwrite     fg_mix, HWMIX_SOURCE
        memregwrite     colour_comp_fun, COLCOMP_ALWAYS

        ; set up the SCREEN in pixmap A
        memregwrite     hw_pi_map_index, SEL_PIX_MAP_A

        ; write physical address to hardware mapA base
        mov             eax, _DirectListEntry.phys_addr
        memregwrite     hw_pi_map_base_ptr, eax

        ; write mapA format from screen bitmap header
        mov             ax, _DirectListEntry.hw_format
        memregwrite     hw_pi_map_format, al

        ; write mapA width and height
        mov             eax, dword ptr _DirectListEntry.hw_width
        memregwrite     hw_pi_map_size, eax

        ; set the first PHUNK buffer into pixmap B
        memregwrite     hw_pi_map_index, SEL_PIX_MAP_B

        ; write physical address to hardware mapB base
        mov             eax, _pPhunkPhys
        memregwrite     hw_pi_map_base_ptr, eax

        ; write mapB format from screen bitmap header
        mov             ax, _DirectListEntry.hw_format
        memregwrite     hw_pi_map_format, al

        ; write mapB width (screen width)
        mov             ax, word ptr _DirectListEntry.hw_width
        memregwrite     hw_pi_map_width, ax

        ; write mapB height (1 pel high)
        memregwrite     hw_pi_map_height, 0 ; zero -> 1 pel high

        ; set the blt dimensions
        memregwrite     dim2,0          ; zero -> 1 pel high
        mov     ax,usRectWidth
        memregwrite     dim1,ax

        mov     edi, _pPhunkVirt                                         ;**

        ;***************************************************************
        ; a quick summary of the situation
        ; 
        ; PIX_MAP_A   the screen
        ; PIX_MAP_B   the first scan line buffer (start of the PHUNK)
        ; SEGREG:esi  memory mapped Expressway registers
        ; blt dimension is set to copy 1 scan line of rectangle
        ; edi         is the address of the PHUNK
        ;***************************************************************

        ; now enter a loop for each scanline to process
        mov     cx,usRectHeight
scanloop:
        ; just ensure the HW is not in use
        waitshort

        ; read the scanline into the buffer

        ; set the blt start coordinates
        mov     ax, usXLeft
        memregwrite     src_map_x, ax
        mov     ax, usYBottom
        sub     ax,cx
        memregwrite     src_map_y, ax
        memregwrite     dest_map, 0

        ; start the copy
        ; -  background source: src_pix_map
        ; -  foreground source: src_pix_map
        ; -  step: PxBlt
        ; -  source pixel map: map A
        ; -  destination pixel map: map B
        ; -  pattern pixel map: foreground
        ; -  mask pixel map: boundary disabled
        ; -  drawing mode: don't care
        ; -  direction octant: left to right, top to bottom
        memregwrite     pixel_op, 0A8128000h

        ; process this scanline
        ; we get the width (in bytes since this is only called at 8bpp)
        ; and round it down to the nearest multiple of dwords
        ; This is then used as a dword pointer so although we round down
        ; we still get 3 bytes beyond the pointer. This is not a problem
        ; because the PHUNK is larger than the size of any scan line (max 2K
        ; for a 16bpp 1024 pel scan line) and so the extra bytes accessed
        ; will not cause a GP fault.
        mov     dx,usRectWidth  ; get the width
        and     edx,0FFFCh      ; round it down to a multiple of dwords ;**
        xor     ebx,ebx         ; we are going to use bx as a table pointer ;**

        ; wait until the scanline is in the buffer
        waitshort

pel4loop:
        ; Get four bytes from the buffer
        mov     eax, [edi][edx]

        ; Convert the bottom word
        mov     bl, al
        mov     al, byte ptr _UCMapping[ebx]                             ;**
        mov     bl, ah
        mov     ah, byte ptr _UCMapping[ebx]                             ;**

        ; Get the top word into ax
        swap    eax

        ; Convert the top word
        mov     bl, al
        mov     al, byte ptr _UCMapping[ebx]                             ;**
        mov     bl, ah
        mov     ah, byte ptr _UCMapping[ebx]                             ;**

        ; Get back the bottom word into ax
        swap    eax

        ; Store the converted double word back into the buffer
        mov     [edi][edx], eax                                         ;**

        ; Move the index to the next four bytes to be processed in the buffer
        sub     edx, 4                                                  ;**

        ; Loop back if we have not finished
        ; this test relies on the fact that the buffer starts at address 0
        jnc     pel4loop

        ; copy the processed scanline back to the screen

        ; set the blt start coordinates
        mov     ax, usXLeft
        memregwrite     dest_map_x, ax
        mov     ax, usYBottom
        sub     ax,cx
        memregwrite     dest_map_y, ax
        memregwrite     src_map, 0

        ; start the copy
        ; -  background source: src_pix_map
        ; -  foreground source: src_pix_map
        ; -  step: PxBlt
        ; -  source pixel map: map B
        ; -  destination pixel map: map A
        ; -  pattern pixel map: foreground
        ; -  mask pixel map: boundary disabled
        ; -  drawing mode: don't care
        ; -  direction octant: left to right, top to bottom
        memregwrite     pixel_op, 0A8218000h

        dec     cx
        jnz     scanloop

        popxga                  ; restore the segment register used for XGA
cEnd

_TEXT   ends

endif ; PALETTE_MGR
        end



ifdef PARALLEL
; This is sort of spec/code for a version of this routine which
; uses the parallelism of the h/w as much as possible.
; If this function is actually used, then we could spend more time
; actually implenting this more complex version.

        ; set the second PHUNK buffer into pixmap C
        memregwrite     pi_map_index, SEL_PIX_MAP_C

        ; write physical address to hardware mapC base
        xor     eax,eax         ; ensure zero in high word of eax
        mov     ax, word ptr _DirectListEntry.width
        add     eax, _pPhunkPhys
        memregwrite     pi_map_base_ptr, eax

        ; write mapC format from screen bitmap header
        mov             ax, _DirectListEntry.hw_format
        memregwrite     pi_map_format, al

        ; write mapC width (screen width)
        mov             ax, dword ptr _DirectListEntry.hw_width
        memregwrite     pi_map_width, ax

        ; write mapC height (1 pel high)
        xor     ax,ax                   ; zero -> 1 pel
        memregwrite     pi_map_width, ax

        ;***************************************************************
        ; a quick summary of the situation
        ; 
        ; PIX_MAP_A     the screen
        ; PIX_MAP_B     the first scan line buffer (start of the PHUNK)
        ; PIX_MAP_C     the second scan line buffer (also in the PHUNK)
        ; SEGREG:esi    memory mapped Expressway registers
        ; 
        ; What we are going to do now is to utilize double buffering.
        ; This is in order to get the maximum benefit from the fact that
        ; the main processor and the Expressway coprocessor can work in
        ; parallel.
        ; 
        ; Thus the algorithm is (using pseudo OCCAM)
        ; 
        ;       SEQ
        ;         read scanline start into buffer 1
        ;         PAR
        ;           read scanline start+1 into buffer 2
        ;           process buffer 1
        ;         SEQ scanline = start+1 FOR end-start
        ;           SEQ
        ;             PAR
        ;               write buffer 1 back to screen
        ;               process half of buffer 2
        ;             PAR
        ;               read scanline into buffer 1
        ;               process second half of buffer 2
        ;             PAR
        ;               write buffer 2 back to screen
        ;               process half of buffer 1
        ;             PAR
        ;               read scanline+1 into buffer 2
        ;               process second half of buffer 1
        ;         PAR
        ;           write buffer 1 back to screen
        ;           process buffer 2
        ;         write buffer 2 back to screen
        ; 
        ; SEQ represents tasks to be done sequentially
        ; PAR represents tasks to be done in parallel
        ;  to do things in parallel the following form is used:
        ;       waitforHW               ; resynchronise with coprocessor
        ;       set up HW for next operation
        ;       kick off HW
        ;       do processing in software (in parallel with HW)
        ; 
        ;***************************************************************
endif ; PARALLEL
