You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1151 lines
32 KiB
1151 lines
32 KiB
/****************************************************************************
|
|
*****************************************************************************
|
|
*
|
|
* ******************************************
|
|
* * 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);
|
|
}
|
|
|