/*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.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/*   Module          = EDDMERAS                                       */
/*                                                                    */
/*   Description     = Display Device Driver function ErasePS         */
/*                                                                    */
/*   Function        = ErasePS clears the bitmap/screen associated    */
/*                     with the supplied DC.                          */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/**********************************************************************/
#define INCL_DDICOMFLAGS
#define INCL_DDIMISC
#define INCL_WINSYS
#include <eddinclt.h>

#include <eddhcone.h>
#include <eddfcone.h>

#include <eddhtype.h>

#include <eddbextf.h>
#include <eddcextf.h>
#include <eddgextf.h>
#include <eddmextf.h>
#ifdef DCAF                                                               //DCAF
#include <dcafextf.h>                                                     //DCAF
#endif                                                                    //DCAF

#include <eddftype.h>

#include <cursor.h>
#include <hwaccess.h>
#ifdef VRAMPTR
#include <eddncach.h>
#endif /* VRAMPTR */

extern BITBLTPB         AIxfer;
#ifndef _8514
extern MMReg            ShadowXGARegs;
extern pMMReg           pRealXGARegs;
extern pMMReg           pXGARegs;
#else
extern MM8514Reg        Shadow8514Regs;
extern pMM8514Reg       p8514Regs;
#include <8514.h>
#endif
extern ULONG            PixelOp;
extern BltSPad          SPad;
extern CURSORDATA       cursor_data;

extern SHORT                    softDrawInUse;
extern ULONG                    LinePatternCur;
extern ULONG                    LinePatternPhys;
extern ULONG                    LinePatternSys;
extern ULONG                    MarkerCur;
extern ULONG                    MarkerPhys;
extern ULONG                    MarkerSys;
extern ULONG                    pCurCacheBasePhy;
extern ULONG                    pSysCacheStartPhy;
extern drawFunctionsTable       softDrawTable;
extern drawFunctionsTable       hardDrawTable;
extern SHORT                    foregroundSession;
extern pDrawFunctionsTable      pDrawFunctions;
extern BitmapHeader             DirectListEntry;
extern BOOL                     fXgaDead;



/**********************************************************************/
/*                                                                    */
/* ErasePS clears the bitmap/screen associated with the supplied DC   */
/* to the background color. This is either:                           */ //JPB
/*    - the zero entry in the LCT if it has been explicitly defined   */ //JPB
/*    - SYSCLR_WINDOW otherwise.                                      */ //JPB
/*                                                                    */ //JPB
/* The function does not do any correlation checking.                 */
/* Note: I/O subsystems says it should not do bounds, but VGA code    */
/*       does do bounds, so we do bounds.                             */
/*                                                                    */
/*       This function is unaffected by the draw bit (DDK Development */
/*       Guide)                                                       */
/*       !!! DON'T BELIEVE A WORD OF THE ABOVE SENTENCE !!!           */
/*           ... the manual and the VGA comments say that             */
/*           COM_DRAW should be ignored, but the actual VGA code      */
/*           only draws if it is set!                                 */
/*                                                                    */
/**********************************************************************/

DDIENTRY eddm_ErasePS (HDC        hdc,
                       PDC        pdcArg,
                       ULONG      FunN)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    RECTS            Bounds;           /* Bounds rectangle            */
#ifdef DCAF                                                               //DCAF
    RECTL           rclDCAF;                                              //DCAF
#endif                                                                    //DCAF

    /******************************************************************/
    /* Prevent compiler warnings.                                     */
    /******************************************************************/
    IgnoreParam(hdc);

    /******************************************************************/
    /* Get driver semaphore and perform entry checks                  */
    /******************************************************************/
    EnterDriver(pdcArg, FunN, EDF_STANDARD);

    /******************************************************************/
    /* If the function is being called within an area or path         */
    /* definition then we raise an error and leave immediately.       */
    /******************************************************************/
    if (FunNTest(COM_AREA | COM_PATH) )
    {
        if (FunNTest(COM_AREA))
        {
            LogError(PMERR_INV_IN_AREA);
        }
        else /* COM_PATH */
        {
            LogError(PMERR_INV_IN_PATH);
        }
        goto ERASEPS_ERR_EXIT;
    }


    /******************************************************************/
    /* Apply the DC command mask to the command bits                  */
    /******************************************************************/
    COMMANDBITS(FunN) &= pdc->DCICommandMask;

    /******************************************************************/
    /* Check that there is a currently selected bitmap - but that is  */
    /* only required if we are going to do some drawing or calculate  */
    /* bounds                                                         */
    /******************************************************************/
    if ( (pdc->DCIBitmapType == BITMAP_NOT_SELECTED) &&
         (FunNTest(COM_DRAW | COM_ALT_BOUND)))
    {
        LogError(PMERR_NO_BITMAP_SELECTED);
        goto ERASEPS_ERR_EXIT;
    }

    /******************************************************************/
    /* Calculate the bounding rectangle. This is used for cursor      */
    /* exclusion as well as for bounds updating.                      */
    /******************************************************************/
    /* Defect 72798 - We shouldn't query the bitmap if there isn't    */
    /* one.                                                           */
    /******************************************************************/

    if ( ( cursor_data.cursor_status & CURSOR_SOFTWARE ) &&
         (pdc->DCIBitmapType != BITMAP_NOT_SELECTED) )
    {
        Bounds.pts1.x = 0;
        Bounds.pts1.y = 0;
        Bounds.pts2.x = pdc->DCISelListEntry->Info.Width;
        Bounds.pts2.y = pdc->DCISelListEntry->Info.Height;
    }

    /******************************************************************/
    /* Defect 68373 - If we are dead and the destination is the       */
    /* screen then we need to avoid drawing. We do this by            */
    /* turning off the COM_DRAW bit.                                  */
    /******************************************************************/
    if ( fXgaDead && (pdc->DCISelListEntry == &DirectListEntry) )
    {
        COMMANDBITS(FunN) &= ~((USHORT)(COM_DRAW >> 16));
    }

    /******************************************************************/
    /* Check that COM_DRAW is on and that there is at least one clip  */
    /* rectangle.                                                     */
    /* Note the comment at the start of this function about the       */
    /* checking of COM_DRAW.                                          */
    /******************************************************************/
    if ( FunNTest(COM_DRAW) && (pdc->DCIEngineClips) )
    {

        /**************************************************************/
        /* Now it is time to set the drawing mode correctly..         */
        /**************************************************************/
        if (pdc->DCIBitmapType == BITMAP_IS_SCREEN)
        {
            SetDrawModeHard;
        }
        else
        {
            SetDrawModeSoft;
        }

        /**************************************************************/
        /* set up the blt parameter block                             */
        /* target is the selected bitmap (or screen)                  */
        /* clip region data is taken from the dc                      */
        /* source is fixed (ie always foregound).                     */
        /**************************************************************/
        AIxfer.pbmhDest = pdc->DCISelListEntry;
        AIxfer.pNextDestClipRect = pdc->DCIClipRects;

        /**************************************************************/
        /* set up the target to be the bitmap                         */
        /* dimensions and let the blt code worry about clipping       */
        /**************************************************************/
        AIxfer.rcsTrg.pts1.x = 0;
        AIxfer.rcsTrg.pts2.x = AIxfer.pbmhDest->Info.HWWidth;
        AIxfer.rcsTrg.pts1.y = 0;
        AIxfer.rcsTrg.pts2.y = AIxfer.pbmhDest->Info.HWHeight;


        /**************************************************************/
        /* initialise the pixel operation to be used                  */
        /* -  background source: background colour                    */
        /* -  foreground source: foreground colour                    */
        /* -  step: PxBlt                                             */
        /* -  source pixel map: don't care                            */
        /* -  destination pixel map: Map A                            */
        /* -  pattern pixel map: Map B                                */
        /*    NO!! foreground fixed                                   */
        /* -  mask pixel map: boundary disabled                       */
        /* -  drawing mode: don't care                                */
        /* -  direction octant: left to right, top to bottom          */
        /**************************************************************/
        PixelOp = BACK_SRC_BACK_COL |
                  FORE_SRC_FORE_COL |
                  STEP_PXBLT |
                  SRC_PIX_MAP_DONTCARE |
                  DST_PIX_MAP_A |
                  PAT_PIX_MAP_FORE |
                  MASK_PIX_MAP_OFF |
                  DRAW_MODE_DONTCARE |
                  DIR_OCTANT_LRTB;

        /**************************************************************/
        /* exclude and inhibit cursor                                 */
        /**************************************************************/
        if ( cursor_data.cursor_status & CURSOR_SOFTWARE )
        {
            eddm_ExcludeCursor((pDevPoint)&Bounds, COORD_DEVICE_WORD);
        }

        /**************************************************************/
        /* Only need to set foreground mix as using overpaint with a  */
        /* solid fill pattern.                                        */
        /**************************************************************/
   #ifndef _8514
        ShadowXGARegs.FgMix = HWMIX_SOURCE;
        ShadowXGARegs.ColCompCond = COLCOMP_ALWAYS;

        /**************************************************************/
        /* Set up color.                                              */
        /* If in index mode and color zero (the background color) has */
        /* been explicitly defined then use it, otherwise use         */
        /* SYSCLR_WINDOW.                                             */
        /*                                                            */
        /* Defect 65028 - If the DC has a palette loaded then palette */
        /* index 0 should be used as the fill color.                  */
        /**************************************************************/
        if ((pdc->DCIBackgndDefined) || (pdc->DCIColFormat == LCOLF_PALETTE))
        {
            ShadowXGARegs.FgCol = (USHORT)LogToPhyIndex(0L);
        }
        else
        {
            ShadowXGARegs.FgCol = (USHORT)LogToPhyIndex(SYSCLR_WINDOW);
        }
   #else
        Shadow8514Regs.Function_1.Mix = FUNC_S;
        Shadow8514Regs.Function_1.SrcSelect = FUNC_2OP_COL1;
        Shadow8514Regs.Mode.PatternSrc = MD_PS_ONES;
        Shadow8514Regs.Mode.UnderPaint = MD_UP_FALSE;

        /**************************************************************/
        /* Set up color.                                              */
        /* If in index mode and color zero (the background color) has */
        /* been explicitly defined then use it, otherwise use         */
        /* SYSCLR_WINDOW.                                             */
        /*                                                            */
        /* Defect 65028 - If the DC has a palette loaded then palette */
        /* index 0 should be used as the fill color.                  */
        /**************************************************************/
        #ifndef   BPP24
        if ((pdc->DCIBackgndDefined) || (pdc->DCIColFormat == LCOLF_PALETTE))
        {
            Shadow8514Regs.Color_1 = (USHORT)LogToPhyIndex(0L);
        }
        else
        {
            Shadow8514Regs.Color_1 = (USHORT)LogToPhyIndex(SYSCLR_WINDOW);
        }
        #else
        if ((pdc->DCIBackgndDefined) || (pdc->DCIColFormat == LCOLF_PALETTE))
        {
            Shadow8514Regs.Color_1 = LogToPhyIndex(0L);
        }
        else
        {
            Shadow8514Regs.Color_1 = LogToPhyIndex(SYSCLR_WINDOW);
        }
        #endif
   #endif

        /**************************************************************/
        /* Transfer the values from the shadow registers to the real  */
        /* registers.                                                 */
        /**************************************************************/
        TransferShadowRegisters( TSR_COLOUR_MIX );

        /**************************************************************/
        /* everything is ready so call the blt interface              */
        /**************************************************************/

        /**********************************************************/
        /* set the blt function to be used                        */
        /**********************************************************/
        SPad.BltFunction = (*pDrawFunctions)[index_DestOnlyBlt];
        PixBltThroughClips();

        /**************************************************************/
        /* reenable cursor updates                                    */
        /**************************************************************/
        reenable_cursor();

#ifdef VRAMPTR
        /**************************************************************/
        /* If the target bitmap is cached then evict it since it has  */
        /* been drawn to.                                             */
        /**************************************************************/
        if ( BITMAP_IS_CACHED(AIxfer.pbmhDest) )
        {
          evict_cached_bitmap(AIxfer.pbmhDest->bm_cache_slot);
        }
#endif /* VRAMPTR */

    } /*.......if at least one rectangle in the region................*/

    /******************************************************************/
    /* Only update the user bounds (if necessary).                    */
    /* This is similar to what the VGA does. However, we only         */
    /* update the bounds to the bitmap size. The VGA sets them to the */
    /* maximum integers which seems to be unnecessary and confusing   */
    /******************************************************************/
    if (FunNTest(COM_ALT_BOUND))
    {
        Bounds.pts1.x = 0;
        Bounds.pts1.y = 0;
        Bounds.pts2.x = pdc->DCISelListEntry->Info.Width - (USHORT)1;
        Bounds.pts2.y = pdc->DCISelListEntry->Info.Height - (USHORT)1;

        if (pdc->DCIDefUserBounds == TRUE)
        {
            /**************************************************************/
            /* Set current bounds to new bounds and turn flag off         */
            /**************************************************************/
            pdc->DCIUserBounds[0].X = Bounds.pts1.x;
            pdc->DCIUserBounds[0].Y = Bounds.pts1.y;
            pdc->DCIUserBounds[1].X = Bounds.pts2.x;
            pdc->DCIUserBounds[1].Y = Bounds.pts2.y;

            pdc->DCIDefUserBounds = FALSE;
        }
        else  /* current User bounds are not default                */
        {
            /**************************************************************/
            /* Update current bounds with new bounds                      */
            /**************************************************************/
            eddg_AddRectToBounds ((pDevRect)pdc->DCIUserBounds,
                                  (pDevRect)&Bounds,
                                  COORDS_ARE_WORDS);
        }
    }
#ifdef DCAF                                                               //DCAF
    /******************************************************************/  //DCAF
    /* Accumulate DCAF screen bounds if required                      */  //DCAF
    /******************************************************************/  //DCAF
    if (DCAFBoundsRequired(FunN))                                         //DCAF
    {                                                                     //DCAF
        /**************************************************************/  //DCAF
        /* Pass the full screen size through the current clip rects.  */  //DCAF
        /**************************************************************/  //DCAF
        rclDCAF.xLeft = 0;                                                //DCAF
        rclDCAF.yBottom = 0;                                              //DCAF
        rclDCAF.xRight = pdc->DCISelListEntry->Info.Width;                //DCAF
        rclDCAF.yTop = pdc->DCISelListEntry->Info.Height;                 //DCAF
                                                                          //DCAF
        AccumulateScreenBoundsThroughClips( (pDevRect)&rclDCAF, 0L );     //DCAF
    }                                                                     //DCAF
#endif                                                                    //DCAF

    /******************************************************************/
    /* Release driver semaphore                                       */
    /******************************************************************/
    ExitDriver(pdcArg, FunN, EDF_STANDARD);
    return (OK);


ERASEPS_ERR_EXIT:
    /******************************************************************/
    /* Release driver semaphore                                       */
    /******************************************************************/
    ExitDriver(pdcArg, FunN, EDF_STANDARD);
    return (ERROR_ZERO);

} /* eddm_ErasePS */
