📄 blt.cpp
字号:
//I think this way I could Speed up than having a if condition in a loop - SAS
if(Display_BPP == 8){
for (i = 0; i < height; i++)
{
// COPY CURRENT POINTER TO A DWORD POINTER
dataptr = lineptr;
spadAddr = BB0_Base_Address;
// COPY ALL THE DATA FOR THE CURRENT LINE INTO THE SCRATCHPAD
// Must wait for the pipeline to be idle before loading the
// new data into the BLT buffer.
WAIT_PIPELINE(GXregisters);
//Convert the data from 1,2,4,8, 24 to 8
// CHECK SOURCE COLOR DEPTH
switch(srcDepth)
{
case 1:
DataConversion1_2_8(dataptr, sXOffset, width, lookup, spadAddr);
break;
case 2:
DataConversion2_2_8(dataptr, sXOffset, width, lookup, spadAddr);
break;
case 4:
DataConversion4_2_8(dataptr, sXOffset, width, lookup, spadAddr);
break;
case 24:
DataConversion24_2_8(dataptr, width, pBltParms->pConvert, clrConverter, spadAddr);
break;
case 8:
default: //* 8 bit depth
DataConversion8_2_8(dataptr, width, lookup, spadAddr);
break;
}
WRITE_REG16(GXregisters, GP_BLIT_MODE, blit_mode);
// ADJUST SOURCE OFFSET FOR NEXT SCANLINE
lineptr += stride;
}
} else { //Depth == 16
for (i = 0; i < height; i++)
{
// COPY CURRENT POINTER TO A DWORD POINTER
dataptr = lineptr;
spadAddr = BB0_Base_Address;
// COPY ALL THE DATA FOR THE CURRENT LINE INTO THE SCRATCHPAD
// Must wait for the pipeline to be idle before loading the
// new data into the BLT buffer.
WAIT_PIPELINE(GXregisters);
//Convert the data from 1,2,4,8, 24 to 16
switch(srcDepth)
{
case 1:
DataConversion1_2_16(dataptr, sXOffset, width, lookup, spadAddr);
break;
case 2:
DataConversion2_2_16(dataptr, sXOffset, width, lookup, spadAddr);
break;
case 4:
DataConversion4_2_16(dataptr, sXOffset, width, lookup, spadAddr);
break;
case 24:
DataConversion24_2_16(dataptr, width, pBltParms->pConvert, clrConverter, spadAddr);
break;
case 8:
default: //* 8 bit depth
DataConversion8_2_16(dataptr, width, lookup, spadAddr);
break;
}
WRITE_REG16(GXregisters, GP_BLIT_MODE, blit_mode);
// ADJUST SOURCE OFFSET FOR NEXT SCANLINE
lineptr += stride;
}
}
return S_OK;
}
//----------------------------------------------------------------------------
// AcceleratedMaskCopyBlt
//
// This routine is called to perform a screen to screen BLT when a mask is
// involved.
//
// This routine is does not really implement the 0xCCAA raster operation
// corrrectly. It emulates a mask BLT by performing and AND/OR combination.
// It first uses the mask to AND the destination location, then uses a
// source to destination BLT with OR.
//
//----------------------------------------------------------------------------
SCODE GxVideo::AcceleratedMaskCopyBlt( GPEBltParms *pBltParms )
{
DEBUGMSG(0,(TEXT("AcceleratedMaskCopyBlt\n")));
GxVideoSurf *dst = (GxVideoSurf *)(pBltParms->pDst);
int left = dst->Left();
int top = dst->Top();
int x1 = pBltParms->prclDst->left + left;
int y1 = pBltParms->prclDst->top + top;
int x2 = pBltParms->prclDst->right + left;
int y2 = pBltParms->prclDst->bottom + top;
int srcX, srcY, maskX, maskY;
int mstride,sstride;
unsigned long spadAddr, i, j, width, height, width_bytes, bytes;
unsigned char *dataptr, *maskptr, *srcptr;
EGPEFormat format;
// GET RECTANGLE PARAMETERS
width = x2 - x1;
height = y2 - y1;
// Caller assures a well-ordered, non-empty rect
//ASSERT(width > 0 && height > 0);
//-----------------------//
// FIRST DO "AND" MASK //
//-----------------------//
srcptr = (unsigned char *) pBltParms->pSrc->Buffer();
sstride = pBltParms->pSrc->Stride();
format = pBltParms->pSrc->Format();
mstride = pBltParms->pMask->Stride();
maskX = pBltParms->prclMask->left;
maskY = pBltParms->prclMask->top;
width_bytes = (width + (maskX & 7) + 7) >> 3;
maskptr = (unsigned char *) pBltParms->pMask->Buffer();
maskptr += (maskY * mstride) + (maskX >> 3);
DEBUGMSG(0,(TEXT("%d %d %d %d, %d %d, %d %d,%X %X, %d %d, %x\n"),
x1, y1, x2, y2, width, height, sstride, mstride,maskX, maskY,
Display_BPP,format, maskptr));
//Get a valid data pointer
//ASSERT(lineptr !=0);
//First do an AND on Destination and black the area of the actual bitmap area.
//This step is independent of the depth
// SET PARAMETERS FOR ALL SCANLINES
WAIT_PENDING(GXregisters);
WRITE_REG16(GXregisters, GP_SRC_XCOOR, maskX & 7);
WRITE_REG16(GXregisters, GP_DST_XCOOR, x1);
WRITE_REG16(GXregisters, GP_DST_YCOOR, y1);
WRITE_REG16(GXregisters, GP_WIDTH, width);
WRITE_REG16(GXregisters, GP_HEIGHT, 1);
WRITE_REG16(GXregisters, GP_RASTER_MODE, 0x0088);
WRITE_REG32(GXregisters, GP_SRC_COLOR_0, 0xFFFF0000);
// REPEAT FOR EACH SCANLINE
for (j = 0; j < height; j++)
{
// COPY CURRENT POINTER TO A DWORD POINTER
dataptr = maskptr;
spadAddr = BB0_Base_Address;
// COPY ALL THE DATA FOR THE CURRENT LINE INTO THE SCRATCHPAD
// Must wait for the pipeline to be idle before loading the
// new data into the BLT buffer.
WAIT_BUSY(GXregisters);
bytes = width_bytes;
// LOAD COMPLETE DWORDS
while (bytes > 4)
{
// WRITE DATA TO THE SCRATCHPAD
// The register selector actually points to the beginning
// of the scratchpad (the registers start at offset 0x8000).
WRITE_REG32(GXregisters, spadAddr, *((unsigned long *) dataptr));
dataptr += 4;
spadAddr += 4;
bytes -= 4;
}
// LOAD REMAINING BYTES
for (i = 0; i < bytes; i++)
{
// WRITE DATA TO THE SCRATCHPAD
// The register selector actually points to the beginning
// of the scratchpad (the registers start at offset 0x8000).
WRITE_REG8(GXregisters, spadAddr, *dataptr);
dataptr++;
spadAddr++;
}
// ADJUST SOURCE OFFSET FOR NEXT SCANLINE
maskptr += mstride;
WRITE_REG16(GXregisters, GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_READ_DST_FB1 | BM_SOURCE_EXPAND);
}
//Now strip the area other than the mask in the source
//i.e the bitmap data and the mask combine to form a negative of the first pass
//Now OR it with destination
maskptr = (unsigned char *) pBltParms->pMask->Buffer();
maskptr += (maskY * mstride) + (maskX >> 3);
WAIT_PENDING(GXregisters);
WRITE_REG16(GXregisters, GP_DST_XCOOR, x1);
WRITE_REG16(GXregisters, GP_DST_YCOOR, y1);
WRITE_REG16(GXregisters, GP_WIDTH, width);
WRITE_REG16(GXregisters, GP_HEIGHT, 1);
WRITE_REG16(GXregisters, GP_RASTER_MODE, 0xEE);
if(Display_BPP == 8)
{
unsigned char *srctmp;
srcX = pBltParms->prclSrc->left;// left of source rect
srcY = pBltParms->prclSrc->top ;// top of source rect
srcptr += (srcY * sstride) + srcX; //position to the correct buffer location
DEBUGMSG(0,(TEXT("src 8 %d %d %x\n"), srcX, srcY, srcptr));
for (j = 0; j < height; j++)
{
int mX = maskX & 7;
// COPY CURRENT POINTER TO A DWORD POINTER
dataptr = maskptr;
srctmp = srcptr;
spadAddr = BB0_Base_Address;
// COPY ALL THE DATA FOR THE CURRENT LINE INTO THE SCRATCHPAD
// Must wait for the pipeline to be idle before loading the
// new data into the BLT buffer.
WAIT_BUSY(GXregisters);
for (i = 0; i < width; )
{
if(mX == 0){
if(*dataptr == 0xFF){
dataptr ++;
mX = 0;
WRITE_REG32(GXregisters, spadAddr, 0x0); //fill with black
spadAddr += 4;
WRITE_REG32(GXregisters, spadAddr, 0x0); //fill with black
spadAddr += 4;
srctmp += 8;
i += 8; //increment counter
continue;
}
if(*dataptr == 0x00){
dataptr ++;
mX = 0;
WRITE_REG32(GXregisters, spadAddr, *((unsigned long *)srctmp));
spadAddr += 4;
srctmp += 4;//increment the source location
WRITE_REG32(GXregisters, spadAddr, *((unsigned long *)srctmp));
spadAddr += 4;
srctmp += 4;//increment the source location
i += 8; //increment counter
continue;
}
}
if(*dataptr & bit_mask[mX]){
WRITE_REG8(GXregisters, spadAddr, 0x0); //fill with black
} else {
WRITE_REG8(GXregisters, spadAddr, *srctmp);
}
mX++; //increment the mask location
if(mX == 8){
dataptr ++;
mX=0; //roll over
}
spadAddr++;
srctmp++; //increment the source location
i++; //increment counter
}
// ADJUST SOURCE OFFSET FOR NEXT SCANLINE
maskptr += mstride;
srcptr += sstride;
WRITE_REG16(GXregisters, GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_READ_DST_FB1);
}
} else { //Display is assumed to be in 16 bit mode, the only posibility
unsigned short *srctmp;
srcX = pBltParms->prclSrc->left;// left of source rect
srcY = pBltParms->prclSrc->top ;// top of source rect
srcptr += (srcY * sstride) + (srcX << 1); //position to the correct buffer location
DEBUGMSG(0,(TEXT("src 16 %d %d %x\n"), srcX, srcY, srcptr));
for (j = 0; j < height; j++)
{
int mX = maskX & 7;
// COPY CURRENT POINTER TO A DWORD POINTER
dataptr = maskptr;
srctmp = (unsigned short *)srcptr;
spadAddr = BB0_Base_Address;
// COPY ALL THE DATA FOR THE CURRENT LINE INTO THE SCRATCHPAD
// Must wait for the pipeline to be idle before loading the
// new data into the BLT buffer.
WAIT_BUSY(GXregisters);
for (i = 0; i < width; i++)
{
if(mX == 0){
int k;
if(*dataptr == 0xFF){
dataptr ++;
mX = 0;
for(k=0;k<4;k++){
WRITE_REG32(GXregisters, spadAddr, 0x0); //fill with black
spadAddr += 4;
}
srctmp += 8;//increment the source location
i += 8; //increment counter
continue;
}
if(*dataptr == 0x00){
dataptr ++;
mX = 0;
for(k=0;k<4;k++){
WRITE_REG32(GXregisters, spadAddr, *((unsigned long *)srctmp));
spadAddr += 4;
srctmp += 2;//increment the source location
}
i += 8; //increment counter
continue;
}
}
if(*dataptr & bit_mask[mX]){
WRITE_REG16(GXregisters, spadAddr, 0x0); //fill with black
} else {
WRITE_REG16(GXregisters, spadAddr, *srctmp);
}
mX++; //increment the mask location
if(mX == 8){ //Mask is 8 bit
dataptr ++;
mX=0; //roll over
}
spadAddr += 2;
srctmp++; //increment the source location
}
// ADJUST SOURCE OFFSET FOR NEXT SCANLINE
maskptr += mstride;
srcptr += sstride;
WRITE_REG16(GXregisters, GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_READ_DST_FB1);
}
}
return S_OK;
}
//----------------------------------------------------------------------------
// AcceleratedPatternFill
//
//----------------------------------------------------------------------------
SCODE GxVideo::AcceleratedPatternFill( GPEBltParms *pBltParms )
{
DEBUGMSG(0,(TEXT("AcceleratedPatternFill\n")));
GxVideoSurf *dst = (GxVideoSurf *)(pBltParms->pDst);
int left = dst->Left();
int top = dst->Top();
int x1 = pBltParms->prclDst->left + lef
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -