Skip to content

Commit

Permalink
Rewritten blit functions to support 32bpp.
Browse files Browse the repository at this point in the history
  • Loading branch information
maxrd2 committed Oct 29, 2018
1 parent 4307223 commit 6ab4515
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 166 deletions.
1 change: 0 additions & 1 deletion src/sgp/VObject.cc
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@ void BltVideoObject(SGPVSurface* const dst, SGPVObject const* const src, UINT16

if (BltIsClipped(src, iDestX, iDestY, usRegionIndex, &ClippingRect))
{
Assert(src->BPP() == 8); // maxrd2
Blt8BPPDataTo16BPPBufferTransparentClip(
reinterpret_cast<UINT16 *>(pBuffer), // FIXME: maxrd2
uiPitch, src, iDestX, iDestY, usRegionIndex, &ClippingRect);
Expand Down
226 changes: 61 additions & 165 deletions src/sgp/VObject_Blitters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2782,7 +2782,7 @@ void Blt8BPPDataTo16BPPBufferShadow( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, H
* and a 16-bit buffer as a destination. */
void Blt8BPPDataTo16BPPBufferTransparent(UINT32* const buf, UINT32 const uiDestPitchBYTES, SGPVObject const* const hSrcVObject, INT32 const iX, INT32 const iY, UINT16 const usIndex)
{
// DONE: maxrd2
// DONE: maxrd2 - OK
Assert(hSrcVObject);
Assert(hSrcVObject->BPP() == 32); // maxrd2
Assert(buf);
Expand All @@ -2808,36 +2808,13 @@ void Blt8BPPDataTo16BPPBufferTransparent(UINT32* const buf, UINT32 const uiDestP
while(height--) {
UINT32 w = width;
while(w--) {
UINT32 op = *src & 0xFF;
*dst = ((*dst >> 8) * (255 - op) / 255) + ((*src >> 8) * op / 255) << 8 | 0xFF;
UINT32 opacity = *src & 0xFF;
*dst = ((*dst >> 8) * (255 - opacity) / 255) + ((*src >> 8) * opacity / 255) << 8 | 0xFF;
dst++;
src++;
}
dst += line_skip;
}
/*
for (;;)
{
UINT8 data = *src++;
if (data == 0)
{
if (--height == 0) break;
dst += line_skip;
}
else if (data & 0x80)
{ // Transparent
dst += data & 0x7F;
}
else
{
do
{
*dst++ = pal[*src++];
}
while (--data != 0);
}
}
*/
}


Expand All @@ -2850,146 +2827,68 @@ Blt8BPPDataTo16BPPBufferTransparentClip
**********************************************************************************************/
void Blt8BPPDataTo16BPPBufferTransparentClip(UINT16* const pBuffer, const UINT32 uiDestPitchBYTES, const SGPVObject* const hSrcVObject, const INT32 iX, const INT32 iY, const UINT16 usIndex, const SGPRect* const clipregion)
{
UINT32 Unblitted;
UINT8 *DestPtr;
UINT32 LineSkip;
INT32 LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight;
INT32 ClipX1, ClipY1, ClipX2, ClipY2;
// UNTESTED: maxrd2

// Assertions
Assert( hSrcVObject != NULL );
Assert( pBuffer != NULL );
Assert(hSrcVObject != NULL);
Assert(hSrcVObject->BPP() == 32);
Assert(pBuffer != NULL);

// Get Offsets from Index into structure
ETRLEObject const& pTrav = hSrcVObject->SubregionProperties(usIndex);
UINT32 const usHeight = pTrav.usHeight;
UINT32 const usWidth = pTrav.usWidth;
const ETRLEObject &etrle = hSrcVObject->SubregionProperties(usIndex);
const UINT32 etrleHeight = etrle.usHeight;
const UINT32 etrleWidth = etrle.usWidth;

// Add to start position of dest buffer
INT32 const iTempX = iX + pTrav.sOffsetX;
INT32 const iTempY = iY + pTrav.sOffsetY;

if(clipregion==NULL)
{
ClipX1=ClippingRect.iLeft;
ClipY1=ClippingRect.iTop;
ClipX2=ClippingRect.iRight;
ClipY2=ClippingRect.iBottom;
}
else
{
ClipX1=clipregion->iLeft;
ClipY1=clipregion->iTop;
ClipX2=clipregion->iRight;
ClipY2=clipregion->iBottom;
INT32 const offsetX = iX + etrle.sOffsetX;
INT32 const offsetY = iY + etrle.sOffsetY;

INT32 ClipX1, ClipY1, ClipX2, ClipY2;
if(clipregion == NULL) {
ClipX1 = ClippingRect.iLeft;
ClipY1 = ClippingRect.iTop;
ClipX2 = ClippingRect.iRight;
ClipY2 = ClippingRect.iBottom;
} else {
ClipX1 = clipregion->iLeft;
ClipY1 = clipregion->iTop;
ClipX2 = clipregion->iRight;
ClipY2 = clipregion->iBottom;
}

// Calculate rows hanging off each side of the screen
LeftSkip=__min(ClipX1 - MIN(ClipX1, iTempX), (INT32)usWidth);
RightSkip=__min(MAX(ClipX2, (iTempX+(INT32)usWidth)) - ClipX2, (INT32)usWidth);
TopSkip=__min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight);
BottomSkip=__min(__max(ClipY2, (iTempY+(INT32)usHeight)) - ClipY2, (INT32)usHeight);
// Calculate rows hanging off each side of the screen (actually it's how much is skipped from etrle object)
const INT32 srcLeftSkip =__min(ClipX1 - MIN(ClipX1, offsetX), (INT32)etrleWidth);
const INT32 srcRightSkip = __min(MAX(ClipX2, (offsetX + (INT32)etrleWidth)) - ClipX2, (INT32)etrleWidth);
const INT32 srcTopSkip = __min(ClipY1 - __min(ClipY1, offsetY), (INT32)etrleHeight);
const INT32 srcBottomSkip = __min(__max(ClipY2, (offsetY + (INT32)etrleHeight)) - ClipY2, (INT32)etrleHeight);

// calculate the remaining rows and columns to blit
BlitLength=((INT32)usWidth-LeftSkip-RightSkip);
BlitHeight=((INT32)usHeight-TopSkip-BottomSkip);

// check if whole thing is clipped
if((LeftSkip >=(INT32)usWidth) || (RightSkip >=(INT32)usWidth))
return;
const INT32 etrleBlitWidth = (INT32(etrleWidth) - srcLeftSkip - srcRightSkip);
INT32 etrleBlitHeight = (INT32(etrleHeight) - srcTopSkip - srcBottomSkip);

// check if whole thing is clipped
if((TopSkip >=(INT32)usHeight) || (BottomSkip >=(INT32)usHeight))
// check if whole etrle is clipped
if(etrleBlitWidth <= 0 || etrleBlitHeight <= 0)
return;

UINT8 const* SrcPtr = hSrcVObject->PixData(pTrav);
DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY+TopSkip)) + ((iTempX+LeftSkip)*2);
UINT16 const* const p16BPPPalette = hSrcVObject->CurrentShade();
LineSkip=(uiDestPitchBYTES-(BlitLength*2));

UINT32 LSCount;
UINT32 PxCount;

while (TopSkip > 0)
{
for (;;)
{
PxCount = *SrcPtr++;
if (PxCount & 0x80) continue;
if (PxCount == 0) break;
SrcPtr += PxCount;
}
TopSkip--;
}

do
{
for (LSCount = LeftSkip; LSCount > 0; LSCount -= PxCount)
{
PxCount = *SrcPtr++;
if (PxCount & 0x80)
{
PxCount &= 0x7F;
if (PxCount > LSCount)
{
PxCount -= LSCount;
LSCount = BlitLength;
goto BlitTransparent;
}
}
else
{
if (PxCount > LSCount)
{
SrcPtr += LSCount;
PxCount -= LSCount;
LSCount = BlitLength;
goto BlitNonTransLoop;
}
SrcPtr += PxCount;
}
}

LSCount = BlitLength;
while (LSCount > 0)
{
PxCount = *SrcPtr++;
if (PxCount & 0x80)
{
BlitTransparent: // skip transparent pixels
PxCount &= 0x7F;
if (PxCount > LSCount) PxCount = LSCount;
LSCount -= PxCount;
DestPtr += 2 * PxCount;
}
else
{
BlitNonTransLoop: // blit non-transparent pixels
if (PxCount > LSCount)
{
Unblitted = PxCount - LSCount;
PxCount = LSCount;
}
else
{
Unblitted = 0;
}
LSCount -= PxCount;

do
{
*(UINT16*)DestPtr = p16BPPPalette[*SrcPtr++];
DestPtr += 2;
}
while (--PxCount > 0);
SrcPtr += Unblitted;
}
const UINT32 pitchPixels = uiDestPitchBYTES / 4;
const UINT32 dstLineSkip = pitchPixels - etrleBlitWidth;
const UINT32 *src = reinterpret_cast<const UINT32 *>(hSrcVObject->PixData(etrle))
+ srcTopSkip * etrleWidth
+ srcLeftSkip;
UINT32 *dst = reinterpret_cast<UINT32 *>(pBuffer)
+ (pitchPixels * (offsetY + srcTopSkip))
+ (offsetX + srcLeftSkip);

while(etrleBlitHeight-- > 0) {
UINT32 w = etrleBlitWidth;
while(w--) {
UINT32 opacity = *src & 0xFF;
*dst = ((*dst >> 8) * (255 - opacity) / 255) + ((*src >> 8) * opacity / 255) << 8 | 0xFF;
dst++;
src++;
}

while (*SrcPtr++ != 0) {} // skip along until we hit and end-of-line marker
DestPtr += LineSkip;
dst += dstLineSkip;
src += srcLeftSkip + srcRightSkip;
}
while (--BlitHeight > 0);
}


Expand Down Expand Up @@ -3017,19 +2916,16 @@ BOOLEAN BltIsClipped(const SGPVObject* const hSrcVObject, const INT32 iX, const
INT32 const iTempX = iX + pTrav.sOffsetX;
INT32 const iTempY = iY + pTrav.sOffsetY;

if(clipregion==NULL)
{
ClipX1=ClippingRect.iLeft;
ClipY1=ClippingRect.iTop;
ClipX2=ClippingRect.iRight;
ClipY2=ClippingRect.iBottom;
}
else
{
ClipX1=clipregion->iLeft;
ClipY1=clipregion->iTop;
ClipX2=clipregion->iRight;
ClipY2=clipregion->iBottom;
if(clipregion == NULL) {
ClipX1 = ClippingRect.iLeft;
ClipY1 = ClippingRect.iTop;
ClipX2 = ClippingRect.iRight;
ClipY2 = ClippingRect.iBottom;
} else {
ClipX1 = clipregion->iLeft;
ClipY1 = clipregion->iTop;
ClipX2 = clipregion->iRight;
ClipY2 = clipregion->iBottom;
}


Expand Down

0 comments on commit 6ab4515

Please sign in to comment.