📄 blt.cpp
字号:
// This routine is called to perform a solid rectangle fill when destination
// data is involved (DSTINVERT, PATINVERT, etc). Since no source data is
// involved, use BB0 to store the DST data and let it spill into BB1. This
// means we never have to check the width of the rectangle to avoid
// overflowing the BLT buffers.
//----------------------------------------------------------------------------
SCODE GxVideo::AcceleratedFillRectDst( GPEBltParms *pBltParms )
{
DEBUGMSG(0,(TEXT("AcceleratedFillRectDst\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;
unsigned long width = x2 - x1;
unsigned long height = y2 - y1;
#ifdef DURANGO
unsigned short color;
color = (unsigned short)GetBltSolidColor(pBltParms);
gfx_set_solid_pattern(color);
gfx_set_raster_operation((unsigned char) pBltParms->rop4);
gfx_pattern_fill(x1,y1,x2 - x1,y2 - y1);
#else
// Caller assures a well-ordered, non-empty rect
//ASSERT(width > 0 && height > 0);
// SETUP RECTANGLE PARAMETERS
// Must wait until there is not a primitive pending before writing to
// the registers.
WAIT_PENDING(GXregisters);
WRITE_REG32(GXregisters, GP_DST_XCOOR, (y1 << 16) | x1);
WRITE_REG16(GXregisters, GP_RASTER_MODE, (unsigned short) pBltParms->rop4 & 0x00FF);
WRITE_REG32(GXregisters, GP_WIDTH, (height << 16) | width);
WRITE_REG16(GXregisters, GP_BLIT_MODE, BM_READ_DST_FB0);
#endif
return S_OK;
}
//----------------------------------------------------------------------------
// AcceleratedSrcCopyBlt
//
// This routine is called to perform a screen to screen BLT. It should only
// be called when the raster operaion is SRCCOPY, meaning that destination
// data is not required. It should not be called for a transparent BLT.
//----------------------------------------------------------------------------
SCODE GxVideo::AcceleratedSrcCopyBlt( GPEBltParms *pBltParms )
{
DEBUGMSG(0,(TEXT("AcceleratedSrcCopyBlt\n")));
GxVideoSurf *dst = (GxVideoSurf *)(pBltParms->pDst);
GxVideoSurf *src = (GxVideoSurf *)(pBltParms->pSrc);
int srcX = pBltParms->prclSrc->left + src->Left(); // left of source rect
int srcY = pBltParms->prclSrc->top + src->Top(); // top of source rect
int dstX = pBltParms->prclDst->left + dst->Left(); // left of dest rect
int dstY = pBltParms->prclDst->top + dst->Top(); // top of dest rect
unsigned long width = pBltParms->prclDst->right - pBltParms->prclDst->left;
unsigned long height = pBltParms->prclDst->bottom - pBltParms->prclDst->top;
unsigned short blit_mode = BM_READ_SRC_FB;
#ifdef DURANGO
gfx_set_solid_pattern(0);
gfx_set_raster_operation((unsigned char) pBltParms->rop4);
if (pBltParms->bltFlags & BLT_TRANSPARENT) {
unsigned short xcolor = (unsigned short) pBltParms->solidColor;
if (Display_BPP == 8)
{
xcolor &= 0x00FF;
xcolor |= (xcolor << 8);
} else
xcolor = (unsigned short)GetBltSolidColor(pBltParms);
gfx_screen_to_screen_xblt((unsigned short) srcX, (unsigned short)srcY,
(unsigned short)dstX, (unsigned short)dstY,
(unsigned short)width, (unsigned short)height, xcolor);
} else {
gfx_screen_to_screen_blt((unsigned short) srcX, (unsigned short)srcY,
(unsigned short)dstX, (unsigned short)dstY,
(unsigned short)width, (unsigned short)height);
}
#else //hrhr
DEBUGMSG(0,(TEXT("%d %d, %d %d, %d %d, %d %d , %d %d\n"),
srcX,srcY,dstX,dstY,width,height, src->Left(), src->Top(),
pBltParms->prclSrc->left, pBltParms->prclSrc->top));
// Caller assures a well-ordered, non-empty rect
//ASSERT(width > 0 && height > 0);
// CHECK IF NEGATIVE Y DIRECTION
// For GX, an entire scanline is read into the BLT buffer, so the X
// direction is not a consideration.
if(!pBltParms->yPositive )
{
srcY += ( height - 1 );
dstY += ( height - 1 );
blit_mode |= BM_REVERSE_Y;
}
// PERFORM SCREEN TO SCREEN BLT
WAIT_PENDING(GXregisters);
WRITE_REG32(GXregisters, GP_SRC_XCOOR, (srcY << 16) | srcX);
WRITE_REG32(GXregisters, GP_DST_XCOOR, (dstY << 16) | dstX);
WRITE_REG32(GXregisters, GP_WIDTH, (height << 16) | width);
WRITE_REG16(GXregisters, GP_RASTER_MODE, (unsigned short) pBltParms->rop4 & 0x00FF);
WRITE_REG16(GXregisters, GP_BLIT_MODE, blit_mode);
#endif
return S_OK;
}
#define memInit() \
unsigned long Cnt=0, *dataLptr=0;\
unsigned char *dataCptr=0;
// Expects memInit() called before we come here.
#define memCopy(dataPtr, destAddr, wordsLen, bytesLen) \
{ \
dataCptr = dataPtr; /* init */ \
\
WAIT_PIPELINE(GXregisters); \
/*Write the count words*/ \
if((wordsLen)) { \
dataLptr = (unsigned long *)(dataPtr); \
for (Cnt = 0; Cnt < (wordsLen); Cnt++) \
{ \
WRITE_REG32(GXregisters, (destAddr), dataLptr[Cnt]);\
\
(destAddr) += 4; \
} \
dataCptr = (unsigned char *)&dataLptr[Cnt]; \
} \
\
/* Now Write the count bytes left */ \
if((bytesLen)) { \
for (Cnt = 0; Cnt < (bytesLen); Cnt++) \
{ \
WRITE_REG8(GXregisters, (destAddr), dataCptr[Cnt]); \
\
(destAddr)++; \
} \
} \
}
//----------------------------------------------------------------------------
// AcceleratedTextBlt
//
// This routine is called when accelerating a text character. A raster
// opreration of 0xAAF0 is used, meaning a pattern fill with a mask.
//
// For MXi, the MONOCHROME_BITMAP request should be used.
//----------------------------------------------------------------------------
SCODE GxVideo::AcceleratedTextBlt( GPEBltParms *pBltParms )
{
DEBUGMSG(0,(TEXT("AcceleratedTextBlt\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;
unsigned long i, bytes, width, height, width_bytes, widthWBytes;
int stride;
unsigned short color, spadAddr;
unsigned char *glyphptr;
unsigned char *dataptr;
// GET CHARACTER PARAMETERS
DEBUGMSG(0,(TEXT("%d %d %d %d, %d %d %d %d\n"),
pBltParms->prclDst->left,
pBltParms->prclDst->top,
pBltParms->prclDst->right,
pBltParms->prclDst->bottom,
pBltParms->prclMask->left,
pBltParms->prclMask->top,
pBltParms->prclMask->right,
pBltParms->prclMask->bottom));
width = x2 - x1;
height = y2 - y1;
// Caller assures a well-ordered, non-empty rect
//ASSERT(width > 0 && height > 0);
stride = pBltParms->pMask->Stride();
srcX = pBltParms->prclMask->left;
srcY = pBltParms->prclMask->top;
width_bytes = (width + (srcX & 0x7) + 7) >> 3;
widthWBytes = width_bytes >> 2;
bytes = width_bytes * height;
glyphptr = (unsigned char *) pBltParms->pMask->Buffer();
//Looking for a valid data pointer
//ASSERT(glyphptr != 0);
glyphptr += (srcY * stride) + (srcX >> 3);
DEBUGMSG(0,(TEXT("%d %d %d %d\n"), srcX, srcY, width_bytes, bytes));
// DETERMINE TEXT COLOR
// For GX, an 8 BPP color must be duplicated into the upper byte.
color = (unsigned short) pBltParms->solidColor;
if (Display_BPP == 8)
{
color &= 0x00FF;
color |= (color << 8);
} else
color = (unsigned short)GetBltSolidColor(pBltParms);
DEBUGMSG(0,(TEXT("color = %X\n"), color));
DEBUGMSG(0,(TEXT("Read BB0=0x%X BB1=0x%X, set 0x%X, 0x%X\n"),
execute_cpu_read(GX_BB0_BASE), execute_cpu_read(GX_BB1_BASE),
BB0_Base_Address, BB1_Base_Address));
#ifdef DURANGO
spadAddr = 0; // - for compile
dataptr = glyphptr; // - for compile
i=0; // - for compile
RETAILMSG(0,(TEXT("Read BB0=0x%X BB1=0x%X, set 0x%X, 0x%X\n"),
execute_cpu_read(GX_BB0_BASE), execute_cpu_read(GX_BB1_BASE),
BB0_Base_Address, BB1_Base_Address));
RETAILMSG( 0, ( TEXT(" Durango Text Blt \n") ) );
color = (unsigned short) pBltParms->solidColor;
glyphptr = (unsigned char *) pBltParms->pMask->Buffer();
unsigned short bgcolor = 0xff;
gfx_set_solid_pattern(0);
gfx_set_mono_source(bgcolor,color,1);
gfx_set_raster_operation(0xcc);
gfx_mono_bitmap_to_screen_blt(srcX,srcY,x1,y1,x2 - x1,y2 - y1,glyphptr,stride);
#else
WAIT_PENDING(GXregisters);
// SET PARAMETERS THAT DO NOT CHANGE PER LINE
WRITE_REG32(GXregisters, GP_SRC_XCOOR, srcX & 7);
WRITE_REG32(GXregisters, GP_DST_XCOOR, (y1 << 16) | x1);
WRITE_REG16(GXregisters, GP_RASTER_MODE, RM_SRC_TRANSPARENT | RM_SRC_COPY);
WRITE_REG16(GXregisters, GP_SRC_COLOR_1, color);
//Do the Memory Init for the copy to follow
memInit();
// CHECK IF BLT CAN FIT WITHIN BLT BUFFERS
// Since destination data is not being used, we can use BB1 as well
// as BB0 (BB1 immediately follows BB0). Therefore, the check to see
// if the data will fit is based on twice the size of BB0.
if (bytes <= (unsigned long)(BB0_Size_Bytes << 1))
{
// LOAD MONOCHROME DATA INTO THE BLT BUFFER
// We must wait for the graphics engine to be idle before loading
// the data since it may still be working on data from a previous
// BLT. If performance becomes a strong issue (using WAIT_BUSY
// here hits performance), it is possible to rewrite this code to
// toggle between using BB0 and BB1 for the character data. If
// that were done, then WAIT_PENDING would be sufficient.
spadAddr = BB0_Base_Address;
width_bytes &= 0x3;
for (i = 0; i < height; i++)
{
// COPY CURRENT POINTER TO A CHAR POINTER
memCopy(glyphptr, spadAddr, widthWBytes, width_bytes);
// ADJUST SOURCE OFFSET FOR NEXT SCANLINE
glyphptr += stride;
}
// RENDER THE ENTIRE CHARACTER AT ONCE
WRITE_REG32(GXregisters, GP_WIDTH, (height << 16) | width);
WRITE_REG16(GXregisters, GP_BLIT_MODE, BM_SOURCE_TEXT | BM_READ_SRC_BB0);
}
else
{
unsigned short BufAddr[2] = {BB0_Base_Address, BB1_Base_Address}; // Buffer address being used
unsigned short BufMask[2] = {BM_READ_SRC_BB0, BM_READ_SRC_BB1}; // Buffer Mask to be used
int BufNo = 0; // Buffer #
// RENDER THE CHARACTER A SCANLINE AT A TIME
// This is done if the amount of data for the entire character is
// too large to fit within the BLT buffer.
WRITE_REG32(GXregisters, GP_WIDTH, 0x10000 | width);
// REPEAT FOR EACH SCANLINE
width_bytes &= 0x3;
for (i = 0; i < height; i++)
{
// COPY CURRENT POINTER TO A CHAR POINTER
dataptr = glyphptr;
spadAddr = BufAddr[BufNo];
// COPY ALL THE DATA FOR THE CURRENT LINE INTO THE SCRATCHPAD
memCopy(dataptr, spadAddr, widthWBytes, width_bytes);
// RENDER THE SCANLINE
// Need to use BM_SOURCE_EXPAND instead of BM_SOURCE_TEXT so
// that the X value remains the same and the Y value is
// incremented by one after each BLT.
WRITE_REG16(GXregisters, GP_BLIT_MODE, BM_SOURCE_EXPAND | BufMask[BufNo]);
// Toggle the buffer to be used after each buffer write
ToggleMode(BufNo);
// ADJUST SOURCE OFFSET FOR NEXT SCANLINE
glyphptr += stride;
}
}
#endif
return S_OK;
}
//----------------------------------------------------------------------------
// AcceleratedBitmapScreenBlt
//
// This routine is called to perform a bitmap to screen BLT.
//
// For GX, the source data is loaded into BB0 and the graphics pipeline
// reads the destination data, if required, into BB1.
//
// POSSIBLE OPTIMIZATIONS:
// - Check to see if the bitmap is small enough to fit entirely in the
// BLT buffer.
// - Change the data load routine to use DWORDS.
//----------------------------------------------------------------------------
SCODE GxVideo::AcceleratedBitmapScreenBlt( GPEBltParms *pBltParms )
{
DEBUGMSG(0,(TEXT("AcceleratedBitmapScreenBlt\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;
unsigned long spadAddr, i, width, height, width_bytes;
int stride;
unsigned char *dataptr, *lineptr;
unsigned short blit_mode=0;
// GET BLT PARAMETERS
width = x2 - x1;
height = y2 - y1;
// Caller assures a well-ordered, non-empty rect
//ASSERT(width > 0 && height > 0);
stride = pBltParms->pSrc->Stride();
srcX = pBltParms->prclSrc->left;
srcY = pBltParms->prclSrc->top;
lineptr = (unsigned char *) pBltParms->pSrc->Buffer();
DEBUGMSG(0,(TEXT("%d %d %d %d %d %d %d %d %d %d %d\n"),
x1, y1, x2, y2, width, height, stride, srcX, srcY,
Display_BPP,pBltParms->pSrc->Format()));
#ifdef DURANGO
spadAddr = 0; //- for compile
dataptr = lineptr; // - for compile
i=0; // - for compile
width_bytes = 0; //- for compile
unsigned short color0, color1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -