📄 fimgse2d.cpp
字号:
* @param prclSrc Source Rectangle
* @param prclDst Destination Rectangle
* @param m_iRotate Rotatation Degree. See also ROT_TYPE type
* @note This funciton performs getting offset for stretchblt algorithm compensation
* @sa ROT_TYPE
*
**/
LONG FIMGSE2D::GetCompensatedOffset(DWORD usSrcValue, DWORD usDstValue)
{
/// Calculate X,Y Offset
float fIncrement;
float fStretchRatio;
float fReferPoint = 0.5;
LONG i =0;
fIncrement = (float)usSrcValue / (float)usDstValue;
fStretchRatio = (float)usDstValue / (float)usSrcValue;
do
{
if(fReferPoint > 1) break;
fReferPoint += fIncrement;
i++;
} while(1);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\n fIncr : %5.6f, fSR: %5.6f, i : %d, Offset : %d"), fIncrement, fStretchRatio, i, (LONG)(fStretchRatio - i)));
return (fStretchRatio < 1) ? 0 : (LONG)(fStretchRatio - i);
}
/**
* @fn FIMGSE2D::StretchBlt_Bilinear(PRECTL prclSrc, PRECTL prclDst, ROT_TYPE m_iRotate)
* @param prclSrc Source Rectangle
* @param prclDst Destination Rectangle
* @param m_iRotate Rotatation Degree. See also ROT_TYPE type
* @note This funciton performs real Stretched Bit blit using 2D HW. this functio can handle rotation case.
* There's predefine macro type for presenting rotation register's setting value
* G2D_ROTATION
* @note This function can not support Multiple Operation ex) mirrored + rotation because of HW
* @sa ROT_TYPE
**/
void FIMGSE2D::StretchBlt_Bilinear(PRECTL prclSrc, PRECTL prclDst, ROT_TYPE m_iRotate)
{
POINT ptCompensatedOffset;
WORD usSrcWidth = 0;
WORD usSrcHeight = 0;
WORD usDstWidth = 0;
WORD usDstHeight = 0;
DWORD uXIncr = 0;
DWORD uYIncr = 0;
DWORD uCmdRegVal=0;
RECTL rectDst;
RECTL rectDstRT; //< If rotation case this value must be corrected.
RECTL rectDstLT;
RECTL rectDstRB;
RECTL rectDstLB;
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\n[2DHW] StretchBlt Entry")));
/// Always LeftTop Coordinate is less than RightBottom for Source and Destination Region
Assert( (prclSrc->left < prclSrc->right) && (prclSrc->top < prclSrc->bottom) );
Assert( (prclDst->left < prclDst->right) && (prclDst->top < prclDst->bottom) );
/// Set Stretch parameter
/// most right and bottom line does not be drawn.
usSrcWidth=(WORD) ABS( prclSrc->right - prclSrc->left);
usDstWidth=(WORD) ABS( prclDst->right - prclDst->left);
usSrcHeight=(WORD) ABS( prclSrc->bottom - prclSrc->top);
usDstHeight=(WORD) ABS( prclDst->bottom - prclDst->top);
if((m_iRotate == ROT_90) ||(m_iRotate == ROT_270) )
{
SWAP(usDstHeight, usDstWidth, WORD);
}
/// Stretch ratio calculation, width and height is include last line
/// ex) 10x10 to 30x30
/// Given Coordinate parameter
/// SrcCoord. (0,0)~(10,10) : srcwidth = 10-0 = 10, srcheight = 10-0 = 10
/// DstCoord. (30,30)~(60,60) : dstwidth = 60-30 = 30, dstheight = 60-30 = 30
/// Actual using coordinate
/// src (0,0)~(9,9)
/// Dst (30,30)~(59,59)
/// Increment calculation : srcwidth/dstwidth = 10/30 = 0.33333...
if(usSrcWidth == usDstWidth && usSrcHeight == usDstHeight)
{
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT), (TEXT("\nThis is not stretch or shrink BLT, redirect to BitBlt, R:%d"), m_iRotate));
BitBlt(prclSrc, prclDst, m_iRotate);
return;
}
/// calculate horizontal length
uXIncr = CalculateXYIncrFormat(usSrcWidth , usDstWidth );
SetXIncr(uXIncr);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nXIncr : %d.%d"), (uXIncr&0x003ff800)>>11, (uXIncr & 0x000007ff)));
/// calculate vertical length
uYIncr = CalculateXYIncrFormat(usSrcHeight , usDstHeight );
SetYIncr(uYIncr);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nYIncr : %d.%d"), (uYIncr&0x003ff800)>>11, (uYIncr & 0x000007ff)));
/// Set Source Region Coordinate
SetCoordinateSrcBlock(prclSrc->left, prclSrc->top, prclSrc->right - 1, prclSrc->bottom - 1);
/// Now We divide destination region by 4 logically.
/// 1. LeftTop Vertical Bar, 2. RightTop Block, 3. LeftBottom Small Block, 4.RightBottom Horizontal Bar
/// 1. LeftTop Vertical Bar
/// This region has destination's height - RightBottom Horizontal bar's height
/// and has width value can be gotten by this fomula :
/// Refered source surface's pixel coordinate = 0.5 + Increment ratio(Src/Dst) * destination's coordinate
/// In stretchBlt, Destination's coordinate always starts from (0,0)
/// Here, Bar's width is (max desitnation's coordinate+1) until refered source surface's pixel coordinate is not over 1.0.
/// ex) 10x10 to 30x30
/// Increment ratio = 10/30 = 0.33333
/// Refered source surface's pixel coordinate = 0.5+0.333*0, 0.5+0.333*1, 0.5+0.333*2
/// 0.5, 0.833 meets this condition. so max destination's coordnate is 1. width is 2
/// then each block of destination's has this region
/// LT = (0,0)~(1,27), LB(0,28)~(1,29), RT(2,0)~(29,27), RB(2,28)~(29,29)
/// real stretch ratio is 30/10 = 3. so 2 is less than 3. we need add offset 1
/// ex) 10x10 to 50x50
/// Increment ratio = 10/50 = 0.2
/// Refered source surface's pixel coordinate = 0.5+0.2*0, 0.5+0.2*1, 0.5+0.2*2, 0.5+0.2*3
/// 0.5, 0.7, 0.9 meets this condition. so max destination's coordinate is 2. width is 3
/// then each block of desitnation's has this region
/// LT = (0,0)~(2,46), LB(0,47)~(2,49), RT(3,0)~(49,47), RB(3,47)~(49,49)
/// real stretch ratio is 50/10 = 5. so 3 is less than 5, we need add offset 2
ptCompensatedOffset.x = GetCompensatedOffset(usSrcWidth, usDstWidth);
ptCompensatedOffset.y = GetCompensatedOffset(usSrcHeight, usDstHeight);
///
/// Calculate Destination Region Coordinate for each rotation degree
if(m_iRotate == ROT_180) //< origin set to (x2,y2)
{
rectDst.left = prclDst->right - 1; //< x2
rectDst.top = prclDst->bottom - 1; //< y2
rectDst.right = 2 * (prclDst->right - 1) - prclDst->left ; //< x2 + (x2 - x1)
rectDst.bottom = 2 * (prclDst->bottom -1) - prclDst->top; //< y2 + (y2 - y1)
}
else if(m_iRotate == ROT_90) //<In this time, Height and Width are swapped.
{
rectDst.left = prclDst->right - 1; //< x2
rectDst.right = prclDst->right - 1 + prclDst->bottom - 1 - prclDst->top; //< x2 + (y2 - y1)
rectDst.top = prclDst->top; //< y1
rectDst.bottom = prclDst->top + prclDst->right - 1 - prclDst->left; //< y1 + (x2 - x1)
}
else if(m_iRotate == ROT_270) //<In this time, Height and Width are swapped.
{
rectDst.left = prclDst->left; //< x1
rectDst.right = prclDst->left + prclDst->bottom - 1- prclDst->top; //< x1 + (y2 - y1)
rectDst.top = prclDst->bottom - 1; //< y2
rectDst.bottom = prclDst->bottom - 1 + prclDst->right - 1- prclDst->left; //< y2 + (x2 - x1)
}
else //< ROT_0
{
rectDst.left = prclDst->left;
rectDst.top = prclDst->top;
rectDst.right = prclDst->right - 1;
rectDst.bottom = prclDst->bottom - 1;
}
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nROT:%d, Src:(%d,%d)~(%d,%d), Dst:(%d,%d)~(%d,%d), OC:(%d,%d)"),
m_iRotate, prclSrc->left, prclSrc->top, prclSrc->right, prclSrc->bottom,
rectDst.left, rectDst.top, rectDst.right, rectDst.bottom, rectDst.left, rectDst.top));
/// Set Destination's Rotation mode
SetRotationMode(m_iRotate);
SetRotationOrg((WORD)rectDst.left, (WORD)rectDst.top);
uCmdRegVal = G2D_STRETCH_BITBLT_BIT;
if(ptCompensatedOffset.x != 0 || ptCompensatedOffset.y != 0)
{
rectDstRB.left = rectDst.left + ptCompensatedOffset.x;
rectDstRB.right = rectDst.right;
rectDstRB.top = rectDst.top + ptCompensatedOffset.y;
rectDstRB.bottom = rectDst.bottom;
SetClipWindow(&rectDstRB); //< Reconfigure clip region as Each Block's region
SetCoordinateDstBlock(rectDstRB.left, rectDstRB.top, rectDstRB.right + ptCompensatedOffset.x, rectDstRB.bottom + ptCompensatedOffset.y);
/// First Issuing for Right Bottom Big Region.
CheckFifo(1);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nRight Bottom Block : Dst:(%d,%d)~(%d,%d)"),
rectDstRB.left, rectDstRB.top, rectDstRB.right, rectDstRB.bottom));
m_pG2DReg->CMDR1 = uCmdRegVal;
rectDstRT.left = rectDstRB.left;
rectDstRT.right = rectDst.right;
rectDstRT.top = rectDst.top;
rectDstRT.bottom = rectDstRB.top - 1;
SetClipWindow(&rectDstRT);
SetCoordinateDstBlock(rectDstRT.left, rectDst.top, rectDst.right + ptCompensatedOffset.x, rectDst.bottom);
/// Second Issuing for Right Top Horizontal Bar Region.(in 0, 180 degree)
CheckFifo(1);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nRight Top Block : Dst:(%d,%d)~(%d,%d)"),
rectDstRT.left, rectDstRT.top, rectDstRT.right, rectDstRT.bottom));
m_pG2DReg->CMDR1 = uCmdRegVal;
rectDstLB.left = rectDst.left;
rectDstLB.right = rectDstRB.left - 1;
rectDstLB.top = rectDstRB.top;
rectDstLB.bottom = rectDst.bottom;
SetClipWindow(&rectDstLB);
SetCoordinateDstBlock(rectDst.left, rectDstLB.top, rectDst.right, rectDstLB.bottom + ptCompensatedOffset.y);
/// Third Issuing for Left Bottom Vertical Bar(in 0,180 degree)
CheckFifo(1);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nLeft Bottom Block : Dst:(%d,%d)~(%d,%d)"),
rectDstLB.left, rectDstLB.top, rectDstLB.right, rectDstLB.bottom));
m_pG2DReg->CMDR1 = uCmdRegVal;
rectDstLT.left = rectDst.left;
rectDstLT.right = rectDstLB.right;
rectDstLT.top = rectDst.top;
rectDstLT.bottom = rectDstRT.bottom;
SetClipWindow(&rectDstLT);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nLeft Top Block : Dst:(%d,%d)~(%d,%d)"),
rectDstLT.left, rectDstLT.top, rectDstLT.right, rectDstLT.bottom));
}
SetCoordinateDstBlock(rectDst.left, rectDst.top, rectDst.right, rectDst.bottom);
/// Last Issuing for Left Top Small Region(in 0,180 degree)
#if (G2D_CMDPROCESSING==G2D_FASTRETURN)
WaitForEmptyFifo(); //< This is check fully empty command fifo.
m_pG2DReg->CMDR1 = uCmdRegVal; // Process Only One Instruction per bitblt request
#elif (G2D_CMDPROCESSING==G2D_INTERRUPT)
CheckFifo(1);
IntEnable();
m_pG2DReg->CMDR1 = uCmdRegVal; // Process Only One Instruction per bitblt request
WaitForSingleObject(m_hInterrupt2D, INFINITE);
IntDisable();
IntPendingClear();
InterruptDone(m_dwSysIntr2D);
#elif (G2D_CMDPROCESSING==G2D_BUSYWAITING)
CheckFifo(1);
IntEnable();
while(!WaitForFinish()); // Polling Style
m_pG2DReg->CMDR1 = uCmdRegVal; // Process Only One Instruction per bitblt request
IntDisable();
#else
#error "CMDPROCESSING TYPE is invalid, Please Check Header Definition"
RETAILMSG(TRUE,(TEXT("\nCMDPROCESSING TYPE is invalid, Please Check Header Definition")));
return FALSE;
#endif
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\n[2DHW] StretchBlt Exit")));
/// TODO: Resource Register clearing can be needed.
}
/// This implementation has distorted stretch result.
void FIMGSE2D::StretchBlt(PRECTL prclSrc, PRECTL prclDst, ROT_TYPE m_iRotate)
{
WORD usSrcWidth = 0;
WORD usSrcHeight = 0;
WORD usDstWidth = 0;
WORD usDstHeight = 0;
DWORD uXYIncr = 0;
DWORD uCmdRegVal=0;
RECTL rectDst; //< If rotation case this value must be corrected.
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("[2DHW] StretchBlt Entry\r\n")));
/// Always LeftTop Coordinate is less than RightBottom for Source and Destination Region
Assert( (prclSrc->left < prclSrc->right) && (prclSrc->top < prclSrc->bottom) );
Assert( (prclDst->left < prclDst->right) && (prclDst->top < prclDst->bottom) );
/// Set Stretch parameter
/// Stretch ratio calculation, width and height is not include last line
usSrcWidth=(WORD) ABS( prclSrc->right - prclSrc->left);
usDstWidth=(WORD) ABS( prclDst->right - prclDst->left);
usSrcHeight=(WORD) ABS( prclSrc->bottom - prclSrc->top);
usDstHeight=(WORD) ABS( prclDst->bottom - prclDst->top);
if((m_iRotate == ROT_90) ||(m_iRotate == ROT_270) )
{
SWAP(usDstHeight, usDstWidth, WORD);
}
/// When Orthogonally Rotated operation is conducted,
if(usSrcWidth == usDstWidth && usSrcHeight == usDstHeight)
{
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT), (TEXT("This is not stretch or shrink BLT, redirect to BitBlt, R:%d\n"), m_iRotate));
BitBlt(prclSrc, prclDst, m_iRotate);
return;
}
uXYIncr = CalculateXYIncrFormat(usSrcWidth -1, usDstWidth -1);
SetXIncr(uXYIncr);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nXIncr : %d.%x"), (uXYIncr&0x003ff800)>>11, (uXYIncr & 0x000007ff)));
uXYIncr = CalculateXYIncrFormat(usSrcHeight -1, usDstHeight -1);
SetYIncr(uXYIncr);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("\nYIncr : %d.%x"), (uXYIncr&0x003ff800)>>11, (uXYIncr & 0x000007ff)));
SetCoordinateSrcBlock(prclSrc->left, prclSrc->top, prclSrc->right - 1, prclSrc->bottom - 1);
if(m_iRotate == ROT_180) //< origin set to (x2,y2)
{
rectDst.left = prclDst->right - 1; //< x2
rectDst.top = prclDst->bottom - 1; //< y2
rectDst.right = 2 * (prclDst->right - 1) - prclDst->left ; //< x2 + (x2 - x1)
rectDst.bottom = 2 * (prclDst->bottom -1) - prclDst->top; //< y2 + (y2 - y1)
}
else if(m_iRotate == ROT_90) //<In this time, Height and Width are swapped.
{
rectDst.left = prclDst->right - 1; //< x2
rectDst.right = prclDst->right - 1 + prclDst->bottom - 1 - prclDst->top; //< x2 + (y2 - y1)
rectDst.top = prclDst->top; //< y1
rectDst.bottom = prclDst->top + prclDst->right - 1 - prclDst->left; //< y1 + (x2 - x1)
}
else if(m_iRotate == ROT_270) //<In this time, Height and Width are swapped.
{
rectDst.left = prclDst->left; //< x1
rectDst.right = prclDst->left + prclDst->bottom - 1- prclDst->top; //< x1 + (y2 - y1)
rectDst.top = prclDst->bottom - 1; //< y2
rectDst.bottom = prclDst->bottom - 1 + prclDst->right - 1- prclDst->left; //< y2 + (x2 - x1)
}
else //< ROT_0
{
rectDst.left = prclDst->left;
rectDst.top = prclDst->top;
rectDst.right = prclDst->right - 1;
rectDst.bottom = prclDst->bottom - 1;
}
/// Set Destination's Rotation mode
SetRotationMode(m_iRotate);
SetRotationOrg((WORD)rectDst.left, (WORD)rectDst.top);
SetCoordinateDstBlock(rectDst.left, rectDst.top, rectDst.right, rectDst.bottom);
RETAILMSG(ZONE_CHECK(ZONE_STRETCHBLT),(TEXT("ROT:%d, Src:(%d,%d)~(%d,%d), Dst:(%d,%d)~(%d,%d), OC:(%d,%d)\r\n"),
m_iRotate, prclSrc->left, prclSrc->top, prclSrc->right, prclSrc->bottom,
rectDst.left, rectDst.top, rectDst.right, rectDst.bottom, rectDst.left, rectDst.top));
uCmdRegVal = G2D_STRETCH_BITBLT_BIT;
#if (G2D_CMDPROCESSING==G2D_FASTRETURN)
WaitForEmptyFifo(); //< This is check fully empty command fifo.
m_pG2DReg->CMDR1 = uCmdRegVal; // Process Only One Instruction per bitblt request
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -