📄 gperotate.cpp
字号:
if (!pParms->pDst->IsRotate())
{
if (pParms->yPositive)
{
dst.RowIncrement = pParms->pDst->Stride();
dst.RowPtr = (unsigned char*)pParms->pDst->Buffer() + pParms->pDst->Stride() * (pParms->prclDst->top + dstYStartSkip);
}
else
{
dst.RowIncrement = -pParms->pDst->Stride();
dst.RowPtr = (unsigned char*)pParms->pDst->Buffer() + pParms->pDst->Stride() * (pParms->prclDst->bottom - 1 - dstYStartSkip);
}
if (pParms->xPositive)
{
dst.BytesPerAccess = dst.Bpp/8;
dst.RowPtr += dst.BytesPerAccess * (pParms->prclDst->left + dstXStartSkip);
}
else
{
dst.BytesPerAccess = -dst.Bpp/8;
dst.RowPtr -= dst.BytesPerAccess * (pParms->prclDst->right - 1 - dstXStartSkip);
}
dst.IsRotate = 0;
dst.Mask = (2 << (dst.Bpp - 1)) - 1;
dst.CacheState = 0; // so it is not marked as dirty
}
else
{
dst.InitPixelIterator((GPESurfRotate *)pParms->pDst, pParms->xPositive, pParms->yPositive, pParms->prclDst,
dstXStartSkip, dstYStartSkip);
}
// Initialize the first source iterator (src0)
PixelIteratorRotate src0;
src0.InitPixelIterator(pParms->pSrc, pParms->xPositive, pParms->yPositive, pParms->prclSrc,
srcXStartSkip, srcYStartSkip-1);
// Initialize the second source iterator (src1)
PixelIteratorRotate src1;
src1.InitPixelIterator(pParms->pSrc, pParms->xPositive, pParms->yPositive, pParms->prclSrc,
srcXStartSkip, srcYStartSkip);
// Compensate for srcXStartSkip and srcYStartSkip.
srcHeight -= srcYStartSkip;
srcWidth -= srcXStartSkip;
// Force a read of the first row.
int ystepOverflow = 1;
for (int y = 0, SrcYPixels = 0; y < height; y++)
{
bool IsSrc0Valid;
bool IsSrc1Valid;
// Initialize the dst row pointer to the next line.
if (dst.IsRotate)
{
dst.CurrentCoord = dst.RowCoord;
dst.RowCoord.y += dst.RowIncrement;
}
else
{
dst.Ptr = dst.RowPtr;
dst.RowPtr += dst.RowIncrement;
}
// Initialize u0 and u1
int u1 = ystep >> 8;
int u0 = 256 - u1;
// Check to see if we need to advance to the next row, or go back to
// the beginning of the current source row.
if (!ystepOverflow)
{
SrcYPixels--;
if (!src0.IsRotate)
{
src0.RowPtr -= src0.RowIncrement;
src1.RowPtr -= src0.RowIncrement;
}
else
{
src0.RowCoord.y -= src0.RowIncrement;
src1.RowCoord.y -= src1.RowIncrement;
}
}
// Initialize the source row pointers to the next line.
if (src0.RowPtr)
{
src0.Ptr = src0.RowPtr;
src0.RowPtr += src0.RowIncrement;
src1.Ptr = src1.RowPtr;
src1.RowPtr += src1.RowIncrement;
}
else if (src0.OrigPtr)
{
src0.CurrentCoord = src0.RowCoord;
src0.RowCoord.y += src0.RowIncrement;
src1.CurrentCoord = src1.RowCoord;
src1.RowCoord.y += src1.RowIncrement;
}
if (SrcYPixels == 0)
{
IsSrc0Valid = false;
}
else
{
IsSrc0Valid = true;
}
if (SrcYPixels < srcHeight)
{
IsSrc1Valid = true;
}
else
{
IsSrc1Valid = false;
}
SrcYPixels++;
if (src0.RowPtr)
{
if (!src0.Is24Bit && IsSrc0Valid)
{
src0.Cache = *(unsigned long *)src0.Ptr;
src0.CacheState = src0.CacheStateNewRow;
}
if (!src1.Is24Bit && IsSrc1Valid)
{
src1.Cache = *(unsigned long *)src1.Ptr;
src1.CacheState = src1.CacheStateNewRow;
}
}
for (int x = 0, SrcXPixels = 0; x < width;)
{
// Save the old values of src0 and src1.
unsigned long OldSrc0Value = src0.Value;
unsigned long OldSrc1Value = src1.Value;
// Only increment the src0 and src1 pointers if we haven't hit the
// end of a row.
if (SrcXPixels < srcWidth)
{
SrcXPixels++;
// Get the next src0 pixel.
if (IsSrc0Valid)
{
if (src0.Ptr)
{
if (src0.Is24Bit)
{
src0.Value = (*src0.Ptr) + (*(src0.Ptr+1) << 8) + (*(src0.Ptr+2) << 16);
src0.Ptr += src0.BytesPerAccess;
}
else
{
if (!(src0.CacheState & 0x00FF00))
{
src0.Ptr += src0.BytesPerAccess;
src0.CacheState = src0.CacheStateNewDWord;
src0.Cache = *(unsigned long *)src0.Ptr;
}
src0.Value = src0.Cache >> ((src0.CacheState >> 16) ^ src0.MaskShiftXor);
src0.CacheState += src0.CacheStateIncrement;
}
}
else
{
switch (src0.Bpp)
{
case 8:
src0.Value = *(unsigned char *)src0.GetPtr();
break;
case 16:
src0.Value = *(unsigned short *)src0.GetPtr();
break;
case 32:
src0.Value = *(unsigned long *)src0.GetPtr();
break;
case 24:
{
unsigned char * ptr = src0.GetPtr();
src0.Value = (*ptr) | (*(ptr+1) << 8) + (*(ptr+2) << 16);
break;
}
}
src0.CurrentCoord.x += src0.ColIncrement;
}
src0.Value &= src0.Mask;
if (pParms->pLookup)
{
src0.Value = (pParms->pLookup)[src0.Value];
}
if (pParms->pConvert)
{
src0.Value = (pParms->pColorConverter->*(pParms->pConvert))(src0.Value);
}
}
// Get the next src1 pixel (if needed).
if (IsSrc1Valid)
{
if (src1.Ptr)
{
if (src1.Is24Bit)
{
src1.Value = (*src1.Ptr) + (*(src1.Ptr+1) << 8) + (*(src1.Ptr+2) << 16);
src1.Ptr += src1.BytesPerAccess;
}
else
{
if (!(src1.CacheState & 0x00FF00))
{
src1.Ptr += src1.BytesPerAccess;
src1.CacheState = src1.CacheStateNewDWord;
src1.Cache = *(unsigned long *)src1.Ptr;
}
src1.Value = src1.Cache >> ((src1.CacheState >> 16) ^ src1.MaskShiftXor);
src1.CacheState += src1.CacheStateIncrement;
}
}
else
{
switch (src1.Bpp)
{
case 8:
src1.Value = *(unsigned char *)src1.GetPtr();
break;
case 16:
src1.Value = *(unsigned short *)src1.GetPtr();
break;
case 32:
src1.Value = *(unsigned long *)src1.GetPtr();
break;
case 24:
{
unsigned char * ptr = src1.GetPtr();
src1.Value = (*ptr) | (*(ptr+1) << 8) + (*(ptr+2) << 16);
break;
}
}
src1.CurrentCoord.x += src1.ColIncrement;
}
src1.Value &= src1.Mask;
if (pParms->pLookup)
{
src1.Value = (pParms->pLookup)[src1.Value];
}
if (pParms->pConvert)
{
src1.Value = (pParms->pColorConverter->*(pParms->pConvert))(src1.Value);
}
}
else
{
src1.Value = src0.Value;
}
if (!IsSrc0Valid)
{
src0.Value = src1.Value;
}
}
// If this is the first pixel read set the old values to this pixel
if (SrcXPixels == 1)
{
OldSrc0Value = src0.Value;
OldSrc1Value = src1.Value;
}
// Combine the pixels according to this algorithm:
// s0 = OldSrc0Value * u0 + OldSrc1Value * u1;
// s1 = src0.Value * u0 + src1.Value * u1;
// SrcValue = s0 * v0 + s1 * v1;
unsigned long s0;
unsigned long s1;
if (OldSrc0Value == OldSrc1Value)
{
s0 = OldSrc0Value;
}
else
{
unsigned long A00aa00gg;
unsigned long A00rr00bb;
A00aa00gg = ((OldSrc0Value & g_BilinearMasks[3]) >> g_BilinearShifts[3]) << 16;
A00aa00gg |= (OldSrc0Value & g_BilinearMasks[1]) >> g_BilinearShifts[1];
A00rr00bb = ((OldSrc0Value & g_BilinearMasks[0]) >> g_BilinearShifts[0]) << 16;
A00rr00bb |= (OldSrc0Value & g_BilinearMasks[2]) >> g_BilinearShifts[2];
unsigned long B00aa00gg;
unsigned long B00rr00bb;
B00aa00gg = ((OldSrc1Value & g_BilinearMasks[3]) >> g_BilinearShifts[3]) << 16;
B00aa00gg |= (OldSrc1Value & g_BilinearMasks[1]) >> g_BilinearShifts[1];
B00rr00bb = ((OldSrc1Value & g_BilinearMasks[0]) >> g_BilinearShifts[0]) << 16;
B00rr00bb |= (OldSrc1Value & g_BilinearMasks[2]) >> g_BilinearShifts[2];
unsigned long Caaaagggg;
unsigned long Crrrrbbbb;
unsigned long Caarrggbb;
Caaaagggg = A00aa00gg * u0 + B00aa00gg * u1;
Crrrrbbbb = (A00rr00bb * u0 + B00rr00bb * u1) >> 8;
Caarrggbb = (Caaaagggg & 0xFF00FF00) | (Crrrrbbbb & 0x00FF00FF);
s0 = (((Caarrggbb & 0x00FF0000) >> 16) << g_BilinearShifts[0])
| (((Caarrggbb & 0x0000FF00) >> 8) << g_BilinearShifts[1])
| ((Caarrggbb & 0x000000FF) << g_BilinearShifts[2])
| (((Caarrggbb & 0xFF000000) >> 24) << g_BilinearShifts[3]);
}
if (src0.Value == src1.Value)
{
s1 = src0.Value;
}
else
{
unsigned long A00aa00gg;
unsigned long A00rr00bb;
A00aa00gg = ((src0.Value & g_BilinearMasks[3]) >> g_BilinearShifts[3]) << 16;
A00aa00gg |= (src0.Value & g_BilinearMasks[1]) >> g_BilinearShifts[1];
A00rr00bb = ((src0.Value & g_BilinearMasks[0]) >> g_BilinearShifts[0]) << 16;
A00rr00bb |= (src0.Value & g_BilinearMasks[2]) >> g_BilinearShifts[2];
unsigned long B00aa00gg;
unsigned long B00rr00bb;
B00aa00gg = ((src1.Value & g_BilinearMasks[3]) >> g_BilinearShifts[3]) << 16;
B00aa00gg |= (src1.Value & g_BilinearMasks[1]) >> g_BilinearShifts[1];
B00rr00bb = ((src1.Value & g_BilinearMasks[0]) >> g_BilinearShifts[0]) << 16;
B00rr00bb |= (src1.Value & g_BilinearMasks[2]) >> g_BilinearShifts[2];
unsigned long Caaaagggg;
unsigned long Crrrrbbbb;
unsigned long Caarrggbb;
Caaaagggg = A00aa00gg * u0 + B00aa00gg * u1;
Crrrrbbbb = (A00rr00bb * u0 + B00rr00bb * u1) >> 8;
Caarrggbb = (Caaaagggg & 0xFF00FF00) | (Crrrrbbbb & 0x00FF00FF);
s1 = (((Caarrggbb & 0x00FF0000) >> 16) << g_BilinearShifts[0])
| (((Caarrggbb & 0x0000FF00) >> 8) << g_BilinearShifts[1])
| ((Caarrggbb & 0x000000FF) << g_BilinearShifts[2])
| (((Caarrggbb & 0xFF000000) >> 24) << g_BilinearShifts[3]);
}
int xstepOverflow = 0;
// Loop through all pixels that can be drawn without changing
// s0 or s1, being careful not to write too many pixels.
while (!xstepOverflow
&& x < width)
{
// x only gets incremented here.
x++;
// Initialize v0 and v1
int v1 = xstep >> 8;
int v0 = 256 - v1;
// Compute the SrcValue.
unsigned long SrcValue;
// See if we can take a short cut.
if (s0 == s1)
{
SrcValue = s0;
}
else
{
unsigned long A00aa00gg;
unsigned long A00rr00bb;
A00aa00gg = ((s0 & g_BilinearMasks[3]) >> g_BilinearShifts[3]) << 16;
A00aa00gg |= (s0 & g_BilinearMasks[1]) >> g_BilinearShifts[1];
A00rr00bb = ((s0 & g_BilinearMasks[0]) >> g_BilinearShifts[0]) << 16;
A00rr00bb |= (s0 & g_BilinearMasks[2]) >> g_BilinearShifts[2];
unsigned long B00aa00gg;
unsigned long B00rr00bb;
B00aa00gg = ((s1 & g_BilinearMasks[3]) >> g_BilinearShifts[3]) << 16;
B00aa00gg |= (s1 & g_BilinearMasks[1]) >> g_BilinearShifts[1];
B00rr00bb = ((s1 & g_BilinearMasks[0]) >> g_BilinearShifts[0]) << 16;
B00rr00bb |= (s1 & g_BilinearMasks[2]) >> g_BilinearShifts[2];
unsigned long Caaaagggg;
unsigned long Crrrrbbbb;
unsigned long Caarrggbb;
Caaaagggg = A00aa00gg * v0 + B00aa00gg * v1;
Crrrrbbbb = (A00rr00bb * v0 + B00rr00bb * v1) >> 8;
Caarrggbb = (Caaaagggg & 0xFF00FF00) | (Crrrrbbbb & 0x00FF00FF);
SrcValue = (((Caarrggbb & 0x00FF0000) >> 16) << g_BilinearShifts[0])
| (((Caarrggbb & 0x0000FF00) >> 8) << g_BilinearShifts[1])
| ((Caarrggbb & 0x000000FF) << g_BilinearShifts[2])
| (((Caarrggbb & 0xFF000000) >> 24) << g_BilinearShifts[3]);
}
// Advance the "x pointer"
xstep += xratio;
xstepOverflow = xstep & (~FIX16_MASK);
xstep &= FIX16_MASK;
// Check to see if a destination read is required.
if (dstMatters)
{
if (dst.IsRotate)
{
switch (dst.Bpp)
{
case 16:
*(unsigned short *)&dst.Value = *(unsigned short *)dst.GetPtr();
break;
case 32:
*(unsigned long *)&dst.Value = *(unsigned long *)dst.GetPtr();
break;
case 24:
{
unsigned char *ptr = dst.GetPtr();
dst.Value = (*ptr) + (*(ptr+1) << 8) + (*(ptr+2) << 16);
break;
}
}
}
else
{
switch (dst.Bpp)
{
case 16:
*(unsigned short *)&dst.Value = *(unsigned short *)dst.Ptr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -