1152 lines
32 KiB
C
1152 lines
32 KiB
C
/****************************************************************************
|
||
*****************************************************************************
|
||
*
|
||
* ******************************************
|
||
* * Copyright (c) 1995, Cirrus Logic, Inc. *
|
||
* * All Rights Reserved *
|
||
* ******************************************
|
||
*
|
||
* PROJECT: Laguna I (CL-GD5462) -
|
||
*
|
||
* FILE: stretch.c
|
||
*
|
||
* AUTHOR: Benny Ng
|
||
*
|
||
* DESCRIPTION:
|
||
* This module implements the DrvStretchBlt() function for the
|
||
* Laguna NT driver.
|
||
*
|
||
* MODULES:
|
||
* AdjustSrcSize()
|
||
* bRectIntersect()
|
||
* cRectIntersect()
|
||
* Shrink()
|
||
* Stretch()
|
||
* CopySrcToOffMem()
|
||
* bStretchDIB()
|
||
* HandleCase_1()
|
||
* DrvStretchBlt()
|
||
*
|
||
* REVISION HISTORY:
|
||
* 7/11/95 Benny Ng Initial version
|
||
*
|
||
* $Log: X:/log/laguna/nt35/displays/cl546x/STRETCH.C $
|
||
*
|
||
* Rev 1.14 Nov 03 1997 11:10:48 frido
|
||
* Added REQUIRE and WRITE_STRING macros.
|
||
*
|
||
* Rev 1.13 08 Apr 1997 12:29:06 einkauf
|
||
*
|
||
* add SYNC_W_3D to coordinate MCD/2D access
|
||
*
|
||
* Rev 1.12 21 Mar 1997 12:22:16 noelv
|
||
* Combined "do_flag" and "sw_test_flag" together into "pointer_switch"
|
||
*
|
||
* Rev 1.11 07 Mar 1997 10:15:58 SueS
|
||
* Handle NULL pointer in DrvStretchBlt.
|
||
*
|
||
* Rev 1.10 06 Sep 1996 15:16:40 noelv
|
||
* Updated NULL driver for 4.0
|
||
*
|
||
* Rev 1.9 20 Aug 1996 11:04:26 noelv
|
||
* Bugfix release from Frido 8-19-96
|
||
*
|
||
* Rev 1.1 15 Aug 1996 11:39:42 frido
|
||
* Added precompiled header.
|
||
*
|
||
* Rev 1.0 14 Aug 1996 17:16:30 frido
|
||
* Initial revision.
|
||
*
|
||
* Rev 1.8 16 May 1996 15:01:40 bennyn
|
||
*
|
||
* Add PIXEL_ALIGN to allocoffscnmem()
|
||
*
|
||
* Rev 1.7 04 Apr 1996 13:20:28 noelv
|
||
* No change.
|
||
*
|
||
* Rev 1.6 15 Mar 1996 09:40:00 andys
|
||
*
|
||
* Removed BITMASK setting from code
|
||
*
|
||
* Rev 1.5 13 Mar 1996 11:11:20 bennyn
|
||
* Added device bitmap support
|
||
*
|
||
* Rev 1.4 07 Mar 1996 18:23:50 bennyn
|
||
*
|
||
* Removed read/modify/write on CONTROL reg
|
||
*
|
||
* Rev 1.3 05 Mar 1996 11:59:10 noelv
|
||
* Frido version 19
|
||
*
|
||
* Rev 1.1 20 Jan 1996 01:16:50 frido
|
||
*
|
||
*
|
||
* Rev 1.5 10 Jan 1996 16:11:12 NOELV
|
||
* Added NULL driver ability.
|
||
*
|
||
* Rev 1.4 18 Oct 1995 14:09:06 NOELV
|
||
*
|
||
* Fixed the mess I made of STRETCH.C I was writing to the BLT extents instea
|
||
*
|
||
* Rev 1.3 18 Oct 1995 12:10:26 NOELV
|
||
*
|
||
* Reworked register writes.
|
||
* punted 16,24, and 32 bpp
|
||
*
|
||
* Rev 1.2 06 Oct 1995 13:50:26 bennyn
|
||
*
|
||
* Rev 1.1 22 Aug 1995 16:40:38 bennyn
|
||
*
|
||
* Rev 1.3 15 Aug 1995 11:27:28 bennyn
|
||
*
|
||
* Rev 1.2 07 Aug 1995 08:02:34 bennyn
|
||
*
|
||
* Rev 1.1 02 Aug 1995 12:13:04 bennyn
|
||
*
|
||
* Rev 1.0 11 Jul 1995 15:14:16 BENNYN
|
||
* Initial revision.
|
||
*
|
||
****************************************************************************
|
||
****************************************************************************/
|
||
|
||
/*----------------------------- INCLUDES ----------------------------------*/
|
||
#include "precomp.h"
|
||
|
||
/*----------------------------- DEFINES -----------------------------------*/
|
||
//#define PUNTBRK
|
||
//#define DBGBRK
|
||
#define DBGDISP
|
||
#define OPTION_1
|
||
//#define OPTION_2
|
||
//#define OPTION_3
|
||
|
||
#define X_INTERP_ENABLE 0x1
|
||
#define Y_INTERP_ENABLE 0x2
|
||
#define X_SHRINK_ENABLE 0x4
|
||
#define Y_SHRINK_ENABLE 0x8
|
||
|
||
#define _32K 32768
|
||
#define SF 0x10000L
|
||
|
||
|
||
/*--------------------- STATIC FUNCTION PROTOTYPES ------------------------*/
|
||
|
||
/*--------------------------- ENUMERATIONS --------------------------------*/
|
||
|
||
/*----------------------------- TYPEDEFS ----------------------------------*/
|
||
typedef union _HOST_DATA {
|
||
BYTE bData[4];
|
||
DWORD dwData;
|
||
} HOST_DATA;
|
||
|
||
|
||
/*-------------------------- STATIC VARIABLES -----------------------------*/
|
||
|
||
/*-------------------------- GLOBAL FUNCTIONS -----------------------------*/
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: AdjustSrcSize()
|
||
*
|
||
* DESCRIPTION: If the destination rectange is changed due to the clipping,
|
||
* the source rectange size need to proportional change.
|
||
* This routine handles the source size change calcualtion.
|
||
*
|
||
* RETURN: TRUE: Punt it.
|
||
*
|
||
* REVISION HISTORY:
|
||
* 7/27/95 Benny Ng Initial version
|
||
****************************************************************************/
|
||
BOOL AdjustSrcSize(LONG dx,
|
||
LONG dy,
|
||
LONG origdx,
|
||
LONG origdy,
|
||
LONG dszX,
|
||
LONG dszY,
|
||
LONG origdszX,
|
||
LONG origdszY,
|
||
LONG *sszX,
|
||
LONG *sszY,
|
||
LONG *XsrcOff,
|
||
LONG *YsrcOff)
|
||
{
|
||
LONG ratioX, ratioY;
|
||
LONG ltemp;
|
||
UINT orig_sszX, orig_sszY;
|
||
|
||
BOOL bpuntit = FALSE;
|
||
|
||
BOOL bStretchX = FALSE;
|
||
BOOL bStretchY = FALSE;
|
||
|
||
orig_sszX = *sszX;
|
||
orig_sszY = *sszY;
|
||
|
||
// -------------------------------------------------------
|
||
// Calculate the source to destination size ratio
|
||
if (*sszX < origdszX)
|
||
{
|
||
ratioX = (origdszX * SF) / *sszX;
|
||
bStretchX = TRUE;
|
||
}
|
||
else
|
||
{
|
||
ratioX = (*sszX * SF) / origdszX;
|
||
};
|
||
|
||
if (*sszY < origdszY)
|
||
{
|
||
ratioY = (origdszY * SF) / *sszY;
|
||
bStretchY = TRUE;
|
||
}
|
||
else
|
||
{
|
||
ratioY = (*sszY * SF) / origdszY;
|
||
};
|
||
|
||
// -------------------------------------------------------
|
||
// Calculate the source X offset
|
||
if (origdx != dx)
|
||
{
|
||
if (bStretchX)
|
||
ltemp = ((dx - origdx) * SF) / ratioX;
|
||
else
|
||
ltemp = ((dx - origdx) * ratioX) / SF;
|
||
|
||
*XsrcOff = ltemp;
|
||
};
|
||
|
||
// Calculate the source X size change
|
||
if (origdszX != dszX)
|
||
{
|
||
if (bStretchX)
|
||
ltemp = ((origdszX - dszX) * SF) / ratioX;
|
||
else
|
||
ltemp = ((origdszX - dszX) * ratioX) / SF;
|
||
|
||
*sszX = *sszX - ltemp;
|
||
};
|
||
|
||
// -------------------------------------------------------
|
||
// Calculate the source Y offset
|
||
if (origdy != dy)
|
||
{
|
||
if (bStretchY)
|
||
ltemp = ((dy - origdy) * SF) / ratioY;
|
||
else
|
||
ltemp = ((dy - origdy) * ratioY) / SF;
|
||
|
||
*YsrcOff = ltemp;
|
||
};
|
||
|
||
// Calculate the source Y size change
|
||
if (origdszY != dszY)
|
||
{
|
||
if (bStretchY)
|
||
ltemp = ((origdszY - dszY) * SF) / ratioY;
|
||
else
|
||
ltemp = ((origdszY - dszY) * ratioY) / SF;
|
||
|
||
*sszY = *sszY - ltemp;
|
||
};
|
||
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "AdjustSrcSize - bpuntit= %x, ratioX=%d, ratioY=%d\n",
|
||
bpuntit, ratioX, ratioY));
|
||
DISPDBG((1, "dx=%d, dy=%d, origdx=%d, origdy=%d,\n",
|
||
dx, dy, origdx, origdy));
|
||
DISPDBG((1, "dszX=%d, dszY=%d, origdszX=%d, origdszY=%d,\n",
|
||
dszX, dszY, origdszX, origdszY));
|
||
DISPDBG((1, "*sszX=%d, *sszY=%d, orig_sszX=%d, orig_sszY=%d,\n",
|
||
*sszX, *sszY, orig_sszX, orig_sszY));
|
||
DISPDBG((1, "*XsrcOff=%d, *YsrcOff=%d\n", *XsrcOff, *YsrcOff));
|
||
#endif
|
||
|
||
#ifdef DBGBRK
|
||
DbgBreakPoint();
|
||
#endif
|
||
|
||
return(bpuntit);
|
||
}
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: bRectIntersect()
|
||
*
|
||
* DESCRIPTION: If 'prcl1' and 'prcl2' intersect, has a return value of
|
||
* TRUE and returns the intersection in 'prclResult'.
|
||
* If they don't intersect, has a return value of FALSE,
|
||
* and 'prclResult' is undefined.
|
||
*
|
||
* RETURN: TRUE: Rectange intersect.
|
||
*
|
||
* REVISION HISTORY:
|
||
* 8/01/95 Benny Ng Initial version
|
||
\**************************************************************************/
|
||
BOOL bRectIntersect(RECTL* prcl1,
|
||
RECTL* prcl2,
|
||
RECTL* prclResult)
|
||
{
|
||
prclResult->left = max(prcl1->left, prcl2->left);
|
||
prclResult->right = min(prcl1->right, prcl2->right);
|
||
|
||
if (prclResult->left < prclResult->right)
|
||
{
|
||
prclResult->top = max(prcl1->top, prcl2->top);
|
||
prclResult->bottom = min(prcl1->bottom, prcl2->bottom);
|
||
|
||
if (prclResult->top < prclResult->bottom)
|
||
return(TRUE);
|
||
};
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: cRectIntersect()
|
||
*
|
||
* DESCRIPTION: This routine takes a list of rectangles from 'prclIn'
|
||
* and clips them in-place to the rectangle 'prclClip'.
|
||
* The input rectangles don't have to intersect 'prclClip';
|
||
* the return value will reflect the number of input rectangles
|
||
* that did intersect, and the intersecting rectangles will
|
||
* be densely packed.
|
||
*
|
||
* RETURN: TRUE: Rectange intersect.
|
||
*
|
||
* REVISION HISTORY:
|
||
* 8/01/95 Benny Ng Initial version
|
||
\**************************************************************************/
|
||
LONG cRectIntersect(RECTL* prclClip,
|
||
RECTL* prclIn, // List of rectangles
|
||
LONG c) // Can be zero
|
||
{
|
||
LONG cIntersections;
|
||
RECTL* prclOut;
|
||
|
||
cIntersections = 0;
|
||
prclOut = prclIn;
|
||
|
||
for (; c != 0; prclIn++, c--)
|
||
{
|
||
prclOut->left = max(prclIn->left, prclClip->left);
|
||
prclOut->right = min(prclIn->right, prclClip->right);
|
||
|
||
if (prclOut->left < prclOut->right)
|
||
{
|
||
prclOut->top = max(prclIn->top, prclClip->top);
|
||
prclOut->bottom = min(prclIn->bottom, prclClip->bottom);
|
||
|
||
if (prclOut->top < prclOut->bottom)
|
||
{
|
||
prclOut++;
|
||
cIntersections++;
|
||
};
|
||
};
|
||
}
|
||
|
||
return(cIntersections);
|
||
}
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: Shrink()
|
||
*
|
||
* DESCRIPTION: This function calculates the parameters for shrink BLT
|
||
* operation.
|
||
*
|
||
* REVISION HISTORY:
|
||
* 7/18/95 Benny Ng Initial version
|
||
****************************************************************************/
|
||
VOID Shrink(PPDEV ppdev,
|
||
LONG lSrc,
|
||
LONG lDst,
|
||
char chCoord,
|
||
ULONG LnCntl,
|
||
LONG *sShrinkInc)
|
||
{
|
||
LONG maj = 0;
|
||
LONG min = 0;
|
||
LONG accum = 0;
|
||
|
||
// Set SHRINKINC value,
|
||
// for y, SHRINKINC = ratio of src/dst
|
||
// for x, SHRINKINC = ratio of src/dst if not interpolating
|
||
// SHRINKINC = (ratio of src/dst minus one) if interpolating
|
||
// low byte for x coordinate
|
||
// high byte for y coordinate
|
||
if (chCoord == 'X')
|
||
{
|
||
*sShrinkInc |= (lSrc / lDst);
|
||
if (LnCntl & X_INTERP_ENABLE)
|
||
sShrinkInc--;
|
||
}
|
||
else
|
||
{
|
||
*sShrinkInc |= ((lSrc / lDst) << 8);
|
||
};
|
||
|
||
// Compute ACCUM_?, MAJ_? and MIN_? values
|
||
// MAJ_? = width (for x) or height (for y) of destination
|
||
// MIN_? = negative of the remainder of src/dst
|
||
// ACCUM_? = MAJ_? - 1 - ( Src%Dst / (shrink factor + 1))
|
||
maj = lDst;
|
||
min = -(lSrc % lDst);
|
||
accum = maj - 1 - ((lSrc % lDst) / ((lSrc / lDst) + 1)) ;
|
||
|
||
if (chCoord == 'X')
|
||
{
|
||
REQUIRE(3);
|
||
LL16 (grMAJ_X, maj);
|
||
LL16 (grMIN_X, min);
|
||
LL16 (grACCUM_X, accum);
|
||
}
|
||
else
|
||
{
|
||
REQUIRE(3);
|
||
LL16 (grMAJ_Y, maj);
|
||
LL16 (grMIN_Y, min);
|
||
LL16 (grACCUM_Y, accum);
|
||
};
|
||
|
||
#ifdef DBGBRK
|
||
DISPDBG((1, "DrvStretchBlt - shrink\n"));
|
||
DbgBreakPoint();
|
||
#endif
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: Stretch()
|
||
*
|
||
* DESCRIPTION: This function calculates the parameters for stretch BLT
|
||
* operation.
|
||
*
|
||
* REVISION HISTORY:
|
||
* 7/18/95 Benny Ng Initial version
|
||
****************************************************************************/
|
||
VOID Stretch(PPDEV ppdev,
|
||
LONG lSrc,
|
||
LONG lDst,
|
||
char chCoord,
|
||
ULONG LnCntl)
|
||
{
|
||
LONG min = 0;
|
||
LONG maj = 0;
|
||
LONG accum = 0;
|
||
|
||
// For interpolated stretches registers values differ from values for
|
||
// replicated stretches
|
||
if (((chCoord == 'X') && ((LnCntl & X_INTERP_ENABLE) == 0)) ||
|
||
((chCoord == 'Y') && ((LnCntl & Y_INTERP_ENABLE) == 0)))
|
||
{
|
||
// Compute ACCUM_?, MAJ_? and MIN_? for replicated stretch
|
||
// MAJ_? = width (for x) or height (for y) of destination
|
||
// MIN_? = negative of width (for x) or height (for y) of source
|
||
// ACCUM_? = MAJ_? - 1 - ( Dst%Src / (stretch factor + 1))
|
||
maj = lDst;
|
||
min = -lSrc;
|
||
accum = maj - 1 - ((lDst % lSrc) / ((lDst / lSrc) + 1));
|
||
}
|
||
else
|
||
{
|
||
// Compute ACCUM_?, MAJ_? and MIN_? for interpolated stretch
|
||
// Interpolated strecthes use bits 13 & 14 of ACCUM_? to determine
|
||
// whether to use pixel A, 3/4 A + 1/4 B, 1/2 A + 1/2 B or
|
||
// 1/4 A + 3/4 B.
|
||
// To set DDA values appropriately there are three choices.
|
||
// 1) Set MAJ_? to 32k and scale MIN_? to keep ratio approximately
|
||
// correct
|
||
// MAJ_? = 32k
|
||
// MIN_? = (negative of ratio of src/dst) scaled up to 32k
|
||
// ACCUM_? = MAJ_? - 1 - (1/2 * Absolute difference of MAJ and MIN)
|
||
//
|
||
// 2) Scale both src and dst appropriately such that the ratio of
|
||
// src/dst is preserved exactly.
|
||
// Note: In the following, the division is performed first thus
|
||
// there is a possiblity of a rounding error which shows the
|
||
// difference between options 1 & 2.
|
||
// MAJ_? = (32k / dst) * dst
|
||
// MIN_? = (32k / dst) * src
|
||
// ACCUM_? = MAJ_? - 1 - (1/2 * Absolute difference of MAJ and MIN)
|
||
//
|
||
// 3) Scale both SRC and Dest in such a manner as to force the last
|
||
// pixels output on a line to match the last source pixels rather
|
||
// than the last source interpolated with the pixel past the end
|
||
// of the line. Option 3 is used here.
|
||
// NOTE: Options 1 and both oversample Src data and so will replicate
|
||
// last pixel in X and interpolate past end of data in Y
|
||
|
||
#ifdef OPTION_1 // Option 1
|
||
maj = _32K;
|
||
min = -((_32K * lSrc) / lDst);
|
||
#endif
|
||
|
||
#ifdef OPTION_2 // Option 2
|
||
maj = ((_32K / lDst) * lDst);
|
||
min = -((_32K / lDst) * lSrc);
|
||
#else // Option 3
|
||
lDst *= 4;
|
||
lSrc = lSrc * 4 - 3;
|
||
maj = ((_32K / lDst) * lDst);
|
||
min = -((_32K / lDst) * lSrc);
|
||
#endif
|
||
|
||
accum = maj - 1 - ((maj % -min) / (lDst/lSrc + 1));
|
||
};
|
||
|
||
if (chCoord == 'X')
|
||
{
|
||
REQUIRE(3);
|
||
LL16 (grMAJ_X, maj);
|
||
LL16 (grMIN_X, min);
|
||
LL16 (grACCUM_X, accum);
|
||
}
|
||
else
|
||
{
|
||
REQUIRE(3);
|
||
LL16 (grMAJ_Y, maj);
|
||
LL16 (grMIN_Y, min);
|
||
LL16 (grACCUM_Y, accum);
|
||
};
|
||
|
||
#ifdef DBGBRK
|
||
DISPDBG((1, "DrvStretchBlt - stretch\n"));
|
||
DbgBreakPoint();
|
||
#endif
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: CopySrcToOffMem()
|
||
*
|
||
* DESCRIPTION: This function copies source data from host memory to
|
||
* offscreen memory
|
||
*
|
||
* REVISION HISTORY:
|
||
* 7/18/95 Benny Ng Initial version
|
||
****************************************************************************/
|
||
VOID CopySrcToOffMem(PPDEV ppdev,
|
||
BYTE *pSrcScan0,
|
||
LONG sDelta,
|
||
LONG sszY,
|
||
POFMHDL SrcHandle)
|
||
{
|
||
LONG DWcnt;
|
||
LONG i, j, k;
|
||
LONG cnt;
|
||
BYTE *pSrcScan;
|
||
PDWORD pSrcData;
|
||
ULONG ultmp;
|
||
LONG Ycord;
|
||
HOST_DATA SrcData;
|
||
|
||
pSrcScan = pSrcScan0;
|
||
Ycord = SrcHandle->aligned_y;
|
||
|
||
// Clear Laguna Command Control Register SWIZ_CNTL bit
|
||
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
|
||
LL16(grCONTROL, ppdev->grCONTROL);
|
||
|
||
pSrcData = &SrcData.dwData;
|
||
DWcnt = sDelta / sizeof(DWORD);
|
||
|
||
// Setup the laguna registers for byte to byte BLT extents
|
||
REQUIRE(8);
|
||
LL16 (grBLTDEF, 0x1020);
|
||
LL16 (grDRAWDEF, 0x00CC);
|
||
|
||
LL16 (grOP1_opRDRAM.pt.X, 0);
|
||
|
||
// LL (grOP0_opMRDRAM.pt.X, SrcHandle->aligned_x);
|
||
// LL (grOP0_opMRDRAM.pt.Y, Ycord);
|
||
LL_OP0_MONO (SrcHandle->aligned_x + ppdev->ptlOffset.x, Ycord + ppdev->ptlOffset.y);
|
||
|
||
// LL (grMBLTEXT_EX.pt.X, sDelta);
|
||
// LL (grMBLTEXT_EX.pt.Y, sszY);
|
||
LL_MBLTEXT (sDelta, sszY);
|
||
|
||
cnt = DWcnt;
|
||
k = 0;
|
||
for (i=0; i < sszY; i++)
|
||
{
|
||
// Pre-fill the 32-bits pattern with default values
|
||
for (j=0; j < 4; j++)
|
||
SrcData.bData[j] = 0;
|
||
|
||
// Copy one screen line mask data from source to destination
|
||
for (j=0; j < sDelta; j++)
|
||
{
|
||
SrcData.bData[k++] = *pSrcScan;
|
||
pSrcScan++;
|
||
|
||
if (k > 3)
|
||
{
|
||
REQUIRE(1);
|
||
LL32 (grHOSTDATA[0], *pSrcData);
|
||
k = 0;
|
||
cnt--;
|
||
}; // endif (k > 3)
|
||
}; // endfor j
|
||
|
||
// Check whether one screen line of data are written to the
|
||
// HOSTDATA register.
|
||
if (cnt == 0)
|
||
{
|
||
// Reset the row data count
|
||
cnt = DWcnt;
|
||
}; // endif (cnt == 0)
|
||
}; // end for i
|
||
|
||
#ifdef DBGBRK
|
||
DISPDBG((0, "DrvStretchBlt-CopySrcToOffMem\n"));
|
||
DbgBreakPoint();
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: bStretchDIB()
|
||
*
|
||
* DESCRIPTION: StretchBlt using integer math. Must be from one surface
|
||
* to another surface of the same format.
|
||
*
|
||
* RETURN: TRUE: Punt it.
|
||
*
|
||
* REVISION HISTORY:
|
||
* 7/27/95 Benny Ng Initial version
|
||
****************************************************************************/
|
||
BOOL bStretchDIB(SURFOBJ* psoSrc,
|
||
SURFOBJ* psoMsk,
|
||
PDEV* ppdev,
|
||
VOID* pvDst,
|
||
LONG lDeltaDst,
|
||
RECTL* prclDst,
|
||
VOID* pvSrc,
|
||
LONG lDeltaSrc,
|
||
RECTL* prclSrc,
|
||
RECTL* prclClip)
|
||
{
|
||
LONG ltmp;
|
||
ULONG ultmp;
|
||
SIZEL reqsz;
|
||
LONG bpp;
|
||
BYTE *pSrcScan;
|
||
RECTL rclRes;
|
||
|
||
BOOL bNoBlt = FALSE;
|
||
BOOL bpuntit = TRUE;
|
||
POFMHDL SrcHandle = NULL;
|
||
|
||
long drawdef = 0;
|
||
long srcx = 0;
|
||
ULONG LnCntl = 0;
|
||
LONG sShrinkInc = 0;
|
||
LONG XsrcOff = 0;
|
||
LONG YsrcOff = 0;
|
||
|
||
// Calculate the rectange start points and sizes:
|
||
//
|
||
LONG WidthDst = prclDst->right - prclDst->left;
|
||
LONG HeightDst = prclDst->bottom - prclDst->top;
|
||
|
||
LONG WidthSrc = prclSrc->right - prclSrc->left;
|
||
LONG HeightSrc = prclSrc->bottom - prclSrc->top;
|
||
|
||
LONG XDstStart = prclDst->left;
|
||
LONG YDstStart = prclDst->top;
|
||
|
||
LONG XSrcStart = prclSrc->left;
|
||
LONG YSrcStart = prclSrc->top;
|
||
|
||
|
||
// -------------------------------------------------------
|
||
// Calculate bytes per pixel
|
||
bpp = ppdev->ulBitCount/8;
|
||
|
||
// Get the informations from source and destination surface
|
||
pSrcScan = pvSrc;
|
||
|
||
if (psoMsk != NULL)
|
||
{
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - HandleCase_1 mask pointer != NULL (punt it)\n"));
|
||
#endif
|
||
|
||
goto Punt_It;
|
||
};
|
||
|
||
// -------------------------------------------------------
|
||
// Check whether source is from host or video memory
|
||
if ((pSrcScan < ppdev->pjScreen) ||
|
||
(pSrcScan > (ppdev->pjScreen + ppdev->lTotalMem)))
|
||
{
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - HandleCase_1 - src host\n"));
|
||
#endif
|
||
|
||
// Allocate the offscreen memory for the source if not enough offscreen
|
||
// memory available punt it.
|
||
reqsz.cx = psoSrc->sizlBitmap.cx;
|
||
reqsz.cy = psoSrc->sizlBitmap.cy;
|
||
|
||
if ((SrcHandle = AllocOffScnMem(ppdev, &reqsz, PIXEL_AlIGN, NULL)) == NULL)
|
||
{ goto Punt_It; };
|
||
|
||
//?? bbbbbbbbbb
|
||
// Note: The following lines of code takes care the host data HW problem,
|
||
// it punt back to GDI when host data size is 29 to 30 to DWORD.
|
||
//
|
||
if ((lDeltaSrc >= 116) && (lDeltaSrc <= 120))
|
||
{
|
||
DISPDBG((1, "DrvStretchBlt - src host (punt it)\n"));
|
||
goto Punt_It;
|
||
};
|
||
//?? eeeeeeeeee
|
||
|
||
// Copy the source data into allocated offscreen memory
|
||
CopySrcToOffMem(ppdev,
|
||
pSrcScan,
|
||
lDeltaSrc,
|
||
HeightSrc,
|
||
SrcHandle);
|
||
|
||
XSrcStart = SrcHandle->aligned_x / bpp;
|
||
YSrcStart = SrcHandle->aligned_y;
|
||
}
|
||
else
|
||
{
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - HandleCase_1 - src videow\n"));
|
||
#endif
|
||
if ((WidthSrc * bpp) > ppdev->lDeltaScreen)
|
||
WidthSrc = ppdev->lDeltaScreen / bpp;
|
||
|
||
ltmp = ppdev->lTotalMem / ppdev->lDeltaScreen;
|
||
|
||
if (HeightSrc > ltmp)
|
||
HeightSrc = ltmp;
|
||
};
|
||
|
||
// -------------------------------------------------------
|
||
if (prclClip != NULL)
|
||
{
|
||
// Test for intersection of clipping rectangle and destination
|
||
// rectangle. If they don't intersect, go on for stretch BLT.
|
||
// For DC_RECT clipping we have a single clipping rectangle.
|
||
// We create a new destination rectangle which is the intersection
|
||
// between the old destination rectangle and the clipping rectangle.
|
||
// Then we adjust our source rectangle accordingly.
|
||
//
|
||
if (!bRectIntersect(prclDst, prclClip, &rclRes))
|
||
{
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - HandleCase_1 - DC_RECT no intersect\n"));
|
||
#endif
|
||
goto Punt_It;
|
||
};
|
||
|
||
// Adjust the source size
|
||
bNoBlt = AdjustSrcSize(rclRes.left, rclRes.top,
|
||
XDstStart, YDstStart,
|
||
(rclRes.right - rclRes.left),
|
||
(rclRes.bottom - rclRes.top),
|
||
WidthDst, HeightDst,
|
||
&WidthSrc, &HeightSrc,
|
||
&XsrcOff, &YsrcOff);
|
||
|
||
// Adjust the destination rectange size
|
||
XDstStart = rclRes.left;
|
||
YDstStart = rclRes.top;
|
||
WidthDst = rclRes.right - rclRes.left;
|
||
HeightDst = rclRes.bottom - rclRes.top;
|
||
}; // endif (prclClip != NULL)
|
||
|
||
if (!bNoBlt)
|
||
{
|
||
// -------------------------------------------------------
|
||
// Perform the shrink or stretch operation
|
||
|
||
// Set the shrink or interpolate bit in LNCNTL
|
||
if (WidthSrc >= WidthDst)
|
||
{
|
||
LnCntl |= X_SHRINK_ENABLE;
|
||
Shrink(ppdev, WidthSrc, WidthDst, 'X', LnCntl, &sShrinkInc);
|
||
}
|
||
else
|
||
{
|
||
Stretch(ppdev, WidthSrc, WidthDst, 'X', LnCntl);
|
||
};
|
||
|
||
if (HeightSrc >= HeightDst)
|
||
{
|
||
LnCntl |= Y_SHRINK_ENABLE;
|
||
Shrink(ppdev, HeightSrc, HeightDst, 'Y', LnCntl, &sShrinkInc);
|
||
}
|
||
else
|
||
{
|
||
Stretch(ppdev, HeightSrc, HeightDst, 'Y', LnCntl);
|
||
};
|
||
|
||
#ifdef DBGBRK
|
||
DISPDBG((1, "DrvStretchBlt - bStretchDIB - before exec\n"));
|
||
DbgBreakPoint();
|
||
#endif
|
||
|
||
// -------------------------------------------------------
|
||
XSrcStart += XsrcOff;
|
||
YSrcStart += YsrcOff;
|
||
|
||
// LL (grOP1_opRDRAM.pt.X, XSrcStart);
|
||
// LL (grOP1_opRDRAM.pt.Y, YSrcStart);
|
||
REQUIRE(12);
|
||
LL_OP1 (XSrcStart, YSrcStart);
|
||
|
||
LL16 (grSHRINKINC, sShrinkInc);
|
||
|
||
LL16 (grBLTDEF, 0x1010);
|
||
LL16 (grDRAWDEF, 0x00CC);
|
||
|
||
// Setup the shrink and interpolate bits in LNCNTL
|
||
ultmp = LLDR_SZ (grLNCNTL.w);
|
||
ultmp |= LnCntl;
|
||
LL16 (grLNCNTL, ultmp);
|
||
|
||
srcx = WidthSrc * bpp;
|
||
LL16 (grSRCX, srcx);
|
||
|
||
// LL (grOP0_opRDRAM.pt.X, XDstStart);
|
||
// LL (grOP0_opRDRAM.pt.Y, YDstStart);
|
||
LL_OP0 (XDstStart + ppdev->ptlOffset.x, YDstStart + ppdev->ptlOffset.y);
|
||
|
||
// LL (grBLTEXTR_EX.pt.X, WidthDst);
|
||
// LL (grBLTEXTR_EX.pt.Y, HeightDst);
|
||
LL_BLTEXTR (WidthDst, HeightDst);
|
||
|
||
#ifdef DBGBRK
|
||
DISPDBG((1, "DrvStretchBlt - bStretchDIB - after exec\n"));
|
||
DbgBreakPoint();
|
||
#endif
|
||
|
||
bpuntit = FALSE;
|
||
}; //endif (!bNoBlt)
|
||
|
||
Punt_It:
|
||
// -------------------------------------------------------
|
||
// Release the offscreen buffer if allocated
|
||
if (SrcHandle != NULL)
|
||
FreeOffScnMem(ppdev, SrcHandle);
|
||
|
||
return(bpuntit);
|
||
}
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: HandleCase_1()
|
||
*
|
||
* DESCRIPTION: This function handle the case when
|
||
* Both src and dst surface types are equal to STYPE_BITMAP,
|
||
* both src and dst surface have same iBitmapFormat,
|
||
* no color translation.
|
||
*
|
||
* RETURN: TRUE: Punt it.
|
||
*
|
||
* REVISION HISTORY:
|
||
* 7/18/95 Benny Ng Initial version
|
||
****************************************************************************/
|
||
BOOL HandleCase_1(SURFOBJ* psoDst,
|
||
SURFOBJ* psoSrc,
|
||
SURFOBJ* psoMsk,
|
||
CLIPOBJ* pco,
|
||
RECTL* prclDst,
|
||
RECTL* prclSrc,
|
||
POINTL* pptlMsk,
|
||
BOOL* bRet)
|
||
{
|
||
BOOL bpuntit = TRUE;
|
||
PDEV* ppdev = (PDEV*) psoDst->dhpdev;
|
||
|
||
BYTE iDComplexity;
|
||
PRECTL prclClip;
|
||
|
||
ENUMRECTS ce;
|
||
BOOL bMore;
|
||
LONG c;
|
||
LONG i;
|
||
|
||
*bRet = FALSE;
|
||
|
||
// -------------------------------------------------------
|
||
// CHeck what kind of clipping is it?
|
||
iDComplexity = (pco ? pco->iDComplexity : DC_TRIVIAL);
|
||
|
||
switch (iDComplexity)
|
||
{
|
||
case DC_TRIVIAL:
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - HandleCase_1 - DC_TRIVIAL\n"));
|
||
#endif
|
||
|
||
bpuntit = bStretchDIB(psoSrc,
|
||
psoMsk,
|
||
ppdev,
|
||
NULL,
|
||
psoDst->lDelta,
|
||
prclDst,
|
||
psoSrc->pvScan0,
|
||
psoSrc->lDelta,
|
||
prclSrc,
|
||
NULL);
|
||
break;
|
||
|
||
case DC_RECT:
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - HandleCase_1 - DC_RECT\n"));
|
||
#endif
|
||
|
||
// Get the clipping rectangle.
|
||
prclClip = &pco->rclBounds;
|
||
|
||
bpuntit = bStretchDIB(psoSrc,
|
||
psoMsk,
|
||
ppdev,
|
||
NULL,
|
||
psoDst->lDelta,
|
||
prclDst,
|
||
psoSrc->pvScan0,
|
||
psoSrc->lDelta,
|
||
prclSrc,
|
||
prclClip);
|
||
break;
|
||
|
||
case DC_COMPLEX:
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - HandleCase_1 - DC_COMPLEX\n"));
|
||
#endif
|
||
|
||
bpuntit = FALSE;
|
||
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
|
||
|
||
do
|
||
{
|
||
bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
|
||
|
||
c = cRectIntersect(prclDst, ce.arcl, ce.c);
|
||
|
||
if (c != 0)
|
||
{
|
||
for (i = 0; i < c; i++)
|
||
{
|
||
bpuntit = bStretchDIB(psoSrc,
|
||
psoMsk,
|
||
ppdev,
|
||
NULL,
|
||
psoDst->lDelta,
|
||
prclDst,
|
||
psoSrc->pvScan0,
|
||
psoSrc->lDelta,
|
||
prclSrc,
|
||
&ce.arcl[i]);
|
||
|
||
if (bpuntit)
|
||
break;
|
||
|
||
}; // enddo
|
||
}; // endif
|
||
|
||
} while ((bMore) && (!bpuntit));
|
||
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}; // end switch (iDComplexity)
|
||
|
||
// -------------------------------------------------------
|
||
// Check whether the operation was handled successfully
|
||
if (!bpuntit)
|
||
*bRet = TRUE;
|
||
|
||
return (bpuntit);
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* FUNCTION NAME: DrvStretchBlt()
|
||
*
|
||
* DESCRIPTION: This function provides stretching bit-block transfer
|
||
* capabilities for Laguna NT
|
||
*
|
||
* REVISION HISTORY:
|
||
* 7/11/95 Benny Ng Initial version
|
||
****************************************************************************/
|
||
#define TSTFRIDO 1
|
||
|
||
BOOL DrvStretchBlt(SURFOBJ* psoDst,
|
||
SURFOBJ* psoSrc,
|
||
SURFOBJ* psoMsk,
|
||
CLIPOBJ* pco,
|
||
XLATEOBJ* pxlo,
|
||
COLORADJUSTMENT* pca,
|
||
POINTL* pptlHTOrg,
|
||
RECTL* prclDst,
|
||
RECTL* prclSrc,
|
||
POINTL* pptlMsk,
|
||
ULONG iMode)
|
||
{
|
||
BOOL bRet = TRUE;
|
||
BOOL bPuntIt = TRUE;
|
||
LONG HandleIt = 0;
|
||
|
||
#if NULL_STRETCH
|
||
{
|
||
if (pointer_switch) return TRUE;
|
||
}
|
||
#endif
|
||
|
||
|
||
#ifdef TSTFRIDO
|
||
{
|
||
PPDEV ppdev = (PPDEV) psoDst->dhpdev;
|
||
SYNC_W_3D(ppdev);
|
||
if (psoDst->iType == STYPE_DEVBITMAP)
|
||
{
|
||
PDSURF pdsurf = (PDSURF)psoDst->dhsurf;
|
||
|
||
if ( pdsurf->pso )
|
||
{
|
||
if ( !bCreateScreenFromDib(ppdev, pdsurf) )
|
||
{
|
||
return EngStretchBlt(psoDst, psoSrc, psoMsk, pco,
|
||
pxlo, pca, pptlHTOrg,
|
||
prclDst, prclSrc, pptlMsk, iMode);
|
||
};
|
||
};
|
||
ppdev->ptlOffset.x = pdsurf->ptl.x;
|
||
ppdev->ptlOffset.y = pdsurf->ptl.y;
|
||
}
|
||
else
|
||
{
|
||
if (ppdev != NULL)
|
||
ppdev->ptlOffset.x = ppdev->ptlOffset.y = 0;
|
||
else
|
||
return(EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca, pptlHTOrg,
|
||
prclDst, prclSrc, pptlMsk, iMode));
|
||
};
|
||
|
||
ppdev = (PPDEV) psoSrc->dhpdev;
|
||
if (psoSrc->iType == STYPE_DEVBITMAP)
|
||
{
|
||
PDSURF pdsurf = (PDSURF)psoSrc->dhsurf;
|
||
|
||
if ( pdsurf->pso )
|
||
{
|
||
if ( !bCreateScreenFromDib(ppdev, pdsurf) )
|
||
{
|
||
return EngStretchBlt(psoDst, psoSrc, psoMsk, pco,
|
||
pxlo, pca, pptlHTOrg,
|
||
prclDst, prclSrc, pptlMsk, iMode);
|
||
};
|
||
};
|
||
ppdev->ptlOffset.x = pdsurf->ptl.x;
|
||
ppdev->ptlOffset.y = pdsurf->ptl.y;
|
||
}
|
||
else
|
||
{
|
||
if (ppdev != NULL)
|
||
ppdev->ptlOffset.x = ppdev->ptlOffset.y = 0;
|
||
else
|
||
return(EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca, pptlHTOrg,
|
||
prclDst, prclSrc, pptlMsk, iMode));
|
||
};
|
||
}
|
||
#else
|
||
{
|
||
PPDEV ppdev = (PPDEV) psoDst->dhpdev;
|
||
SYNC_W_3D(ppdev);
|
||
}
|
||
bRet = EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca, pptlHTOrg,
|
||
prclDst, prclSrc, pptlMsk, iMode);
|
||
return(bRet);
|
||
#endif
|
||
|
||
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - %d\n", iMode));
|
||
#endif
|
||
|
||
if ((psoDst->iType == psoSrc->iType) &&
|
||
(psoDst->fjBitmap == psoSrc->fjBitmap) &&
|
||
(psoDst->fjBitmap == BMF_TOPDOWN))
|
||
{
|
||
// If src and dst surface have same iBitmapFormat
|
||
if (psoDst->iBitmapFormat == psoSrc->iBitmapFormat)
|
||
{
|
||
// Check for color translation
|
||
if (pxlo == NULL)
|
||
{
|
||
HandleIt = 1;
|
||
}
|
||
else if ((pxlo != NULL) && (pxlo->iSrcType == pxlo->iDstType))
|
||
{
|
||
switch (pxlo->flXlate)
|
||
{
|
||
case XO_TRIVIAL:
|
||
case 0:
|
||
HandleIt = 1;
|
||
break;
|
||
|
||
default:
|
||
#ifdef DBGDISP
|
||
DISPDBG((1, "DrvStretchBlt - pxlo->flXlate (punt it)\n"));
|
||
#endif
|
||
break;
|
||
};
|
||
}; // endif (pxlo == NULL)
|
||
}; // endif (src and dst surface have same iBitmapFormat)
|
||
}; // endif (Both src and dst surface types are equal to STYPE_BITMAP)
|
||
|
||
// Check whether we can handle this case, if yes call the case
|
||
// handle routine to try to handle it. Otherwise punt it back to GDI
|
||
if (HandleIt != 0)
|
||
{
|
||
if (HandleIt == 1)
|
||
{
|
||
bPuntIt = HandleCase_1(psoDst,
|
||
psoSrc,
|
||
psoMsk,
|
||
pco,
|
||
prclDst,
|
||
prclSrc,
|
||
pptlMsk,
|
||
&bRet);
|
||
}
|
||
else if (HandleIt == 2)
|
||
{
|
||
};
|
||
}; // endif (HandleIt)
|
||
|
||
// -------------------------------------------------------
|
||
// Punt It back to GDI to handle it
|
||
if (bPuntIt)
|
||
{
|
||
DISPDBG((1, "DrvStretchBlt - punt it\n"));
|
||
|
||
#ifdef PUNTBRK
|
||
DbgBreakPoint();
|
||
#endif
|
||
|
||
bRet = EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca, pptlHTOrg,
|
||
prclDst, prclSrc, pptlMsk, iMode);
|
||
};
|
||
|
||
return(bRet);
|
||
}
|
||
|