📄 rndr_gu1.c
字号:
ScPad ++;
}
#else
for (i = 0; i < section; i++)
{
WRITE_REG8(GFXbb0Base+i, data[line_srcx+offset+i]);
}
#endif
}
/* RENDER FROM BB0 TO FRAME BUFFER */
GFX_WAIT_PENDING;
WRITE_REG16(GP_DST_XCOOR, line_dstx);
WRITE_REG16(GP_DST_YCOOR, dsty);
WRITE_REG16(GP_WIDTH, section);
WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0);
line_width -= section;
line_dstx += section;
line_srcx += section;
}
height--;
dsty++;
offset += pitch;
}
}
/*
//----------------------------------------------------------------------------
// MONOCHROME BITMAP TO SCREEN BLT
//
// This routine transfers monochrome bitmap data to the screen.
//
// SRCX X offset within source bitmap
// SRCY Y offset within source bitmap
// DSTX screen X position to render data
// DSTY screen Y position to render data
// WIDTH width of rectangle, in pixels
// HEIGHT height of rectangle, in scanlines
// *DATA pointer to bitmap data
// PITCH pitch of bitmap data (bytes between scanlines)
//----------------------------------------------------------------------------
*/
#if GFX_2DACCEL_DYNAMIC
void gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
unsigned short dstx, unsigned short dsty, unsigned short width,
unsigned short height, unsigned char *data, short pitch)
#else
void gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy,
unsigned short dstx, unsigned short dsty, unsigned short width,
unsigned short height, unsigned char *data, short pitch)
#endif
{
unsigned short section, buffer_width;
unsigned short blit_mode = BM_READ_SRC_BB0 | BM_SOURCE_EXPAND;
unsigned short line_srcx, line_dstx, line_width;
unsigned short i, bytes;
long offset;
/* CHECK IF ROP REQUIRES DESTINATION DATA */
/* Even bits (0:2:4:6) do not equal corresponding odd bits (1:3:5:7). */
/* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */
if (GFXusesDstData) blit_mode |= BM_READ_DST_FB1;
/* CHECK IF DATA ALREADY IN BLIT BUFFER */
/* If the pointer is NULL, data for the full BLT is already there */
/* WARNING: This could cause problems if destination data is */
/* involved and it overflows the BLT buffer. Need to remove */
/* this option and change the drivers to use a temporary buffer. */
if (!data)
{
GFX_WAIT_PENDING;
WRITE_REG16(GP_SRC_XCOOR, srcx & 7);
WRITE_REG16(GP_DST_XCOOR, dstx);
WRITE_REG16(GP_DST_YCOOR, dsty);
WRITE_REG16(GP_WIDTH, width);
WRITE_REG16(GP_HEIGHT, height);
WRITE_REG16(GP_BLIT_MODE, blit_mode);
return;
}
/* CHECK SIZE OF BLT BUFFER */
buffer_width = GFXbufferWidthPixels;
/* CALCULATE OFFSET INTO BITMAP DATA */
offset = (unsigned long)srcy * (long)pitch;
/* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */
/* Write the registers that do not change for each section. */
GFX_WAIT_PENDING;
WRITE_REG16(GP_HEIGHT, 1);
/* REPEAT FOR EACH SCANLINE */
while(height > 0)
{
line_width = width;
line_srcx = srcx;
line_dstx = dstx;
while(line_width > 0)
{
/* CHECK WIDTH OF CURRENT SECTION */
/* Only divide into sections if reading destination data. */
/* Since the source data is monochrome, it will always fit. */
section = line_width;
if ((line_width > buffer_width) && (blit_mode & BM_READ_DST_FB1))
section = buffer_width;
/* BYTES TO TRANSFER */
/* Add two bytes to handle truncating and alignment. */
bytes = (section >> 3) + 2;
/* TRANSFER SCANLINE OF BITMAP DATA TO BLT BUFFER 0 */
/* Need to wait for BS_PIPELINE_BUSY to make sure that the */
/* data in BB0 for the previous scanline is no longer used. */
/* This can be heavily optimized to not do a byte at a time. */
GFX_WAIT_BUSY;
#ifdef DUROPTI
{
unsigned char *data8 = &data[(line_srcx >> 3) + offset];
unsigned long *data32=0x0;
unsigned short ScPad = GFXbb0Base;
if(bytes >=4 ){ //32 bit
int width_words = bytes / 4;
data32 = (unsigned long *)data8;
for (i = 0; i < width_words; i++)
{
WRITE_REG32(ScPad, data32[i]);
ScPad += 4;
}
data8 = (unsigned char *)&data32[i];
}
for (i = 0; i < (bytes & 0x3); i++)
{
WRITE_REG8(ScPad, data8[i]);
ScPad ++;
}
}
#else
for (i = 0; i < bytes; i++)
{
WRITE_REG8(GFXbb0Base+i, data[(line_srcx >> 3)+offset+i]);
}
#endif
/* RENDER FROM BB0 TO FRAME BUFFER */
GFX_WAIT_PENDING;
WRITE_REG16(GP_DST_XCOOR, line_dstx);
WRITE_REG16(GP_DST_YCOOR, dsty);
WRITE_REG16(GP_SRC_XCOOR, line_srcx & 7);
WRITE_REG16(GP_WIDTH, section);
WRITE_REG16(GP_BLIT_MODE, blit_mode);
line_width -= section;
line_dstx += section;
line_srcx += section;
}
height--;
dsty++;
offset += pitch;
}
}
/*
//----------------------------------------------------------------------------
// BRESENHAM LINE
//
// This routine draws a vector using the specified Bresenham parameters.
// Currently this file does not support a routine that accepts the two
// endpoints of a vector and calculates the Bresenham parameters. If it
// ever does, this routine is still required for vectors that have been
// clipped.
//
// X screen X position to start vector
// Y screen Y position to start vector
// LENGTH length of the vector, in pixels
// INITERR Bresenham initial error term
// AXIALERR Bresenham axial error term
// DIAGERR Bresenham diagonal error term
// FLAGS VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC
//----------------------------------------------------------------------------
*/
#if GFX_2DACCEL_DYNAMIC
void gu1_bresenham_line(unsigned short x, unsigned short y,
unsigned short length, unsigned short initerr,
unsigned short axialerr, unsigned short diagerr,
unsigned short flags)
#else
void gfx_bresenham_line(unsigned short x, unsigned short y,
unsigned short length, unsigned short initerr,
unsigned short axialerr, unsigned short diagerr,
unsigned short flags)
#endif
{
unsigned short vector_mode = flags;
if (GFXusesDstData) vector_mode |= VM_READ_DST_FB;
/* CHECK NULL LENGTH */
if (!length) return;
/* LOAD THE REGISTERS FOR THE VECTOR */
GFX_WAIT_PENDING;
WRITE_REG16(GP_DST_XCOOR, x);
WRITE_REG16(GP_DST_YCOOR, y);
WRITE_REG16(GP_VECTOR_LENGTH, length);
WRITE_REG16(GP_INIT_ERROR, initerr);
WRITE_REG16(GP_AXIAL_ERROR, axialerr);
WRITE_REG16(GP_DIAG_ERROR, diagerr);
WRITE_REG16(GP_VECTOR_MODE, vector_mode);
}
/*---------------------------------------------------------------------------
* GFX_WAIT_UNTIL_IDLE
*
* This routine waits until the graphics engine is idle. This is required
* before allowing direct access to the frame buffer.
*---------------------------------------------------------------------------
*/
#if GFX_2DACCEL_DYNAMIC
void gu1_wait_until_idle(void)
#else
void gfx_wait_until_idle(void)
#endif
{
GFX_WAIT_BUSY;
}
/*---------------------------------------------------------------------------
* GFX_TEST_BLT_PENDING
*
* This routine returns 1 if a BLT is pending, meaning that a call to
* perform a rendering operation would stall. Otherwise it returns 0.
* It is used by Darwin during random testing to only start a BLT
* operation when it knows the Durango routines won't spin on graphics
* (so Darwin can continue to do frame buffer reads and writes).
*---------------------------------------------------------------------------
*/
#if GFX_2DACCEL_DYNAMIC
int gu1_test_blt_pending(void)
#else
int gfx_test_blt_pending(void)
#endif
{
if(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) return(1);
else return(0);
}
/*---------------------------------------------------------------------------
* BLT BUFFERS!!!!!
*---------------------------------------------------------------------------
*/
/* THE BOOT CODE MUST SET THE BLT BUFFER BASES USING THE "CPU_WRITE" */
/* INSTRUCTION TO ONE OF THE FOLLOWING VALUES: */
#define BB0_BASE_2K 0x800
#define BB1_BASE_2K 0xB30
#define BB0_BASE_3K 0x400
#define BB1_BASE_3K 0x930
/*---------------------------------------------------------------------------
* gu1_detect_blt_buffer_base
*
* This detection is hidden from the driver by being called from the
* "gfx_set_bpp" routine.
*
* This is fairly ugly for the following reasons:
*
* - It is the boot code that must set the BLT buffer bases to the
* appropriate values and load the scratchpad tags.
* - The old drivers would also set the base address values to what they
* knew they should be for the 2K or 3K scratchpad configuration.
* - Unfortunately, to set the base addresses requires the use of the
* CPU_WRITE instruction, an instruction specific to GX.
* - Using the CPU_WRITE instruction requires the use of assembly to
* produce the appropriate op codes.
* - Assembly is something that is avoided in Durango because it is not
* platform independent. Some compilers do not support inline assembly.
* - Therefore Durango cannot use the CPU_WRITE instruction.
* - Therefore drivers using Durango must rely on the boot code to set
* the appropriate values. Durango uses this routine to check where
* the base addresses have been set.
* - Unfortunately, it is not as simple as using IO to check for 2K or 3K
* scratchpad size. In VSA1, even though the boot code may set it for
* 3K, SoftVGA comes along and resets it to 2K for it's use in text
* redraws. It used to be that the display driver would set it back
* to 3K.
* - So, the Durango code was changed to just always use 2K.
* - But, the XpressROM code sets it for 3K, and the newer versions of
* SoftVGA do not interfere with that, so then Durango needs to use
* the 3K values to work properly.
* - Therefore, Durango does somewhat of a kludge by writing to directly
* to the scratchpad at both the 2K and 3K locations, then performing
* a unobtrusive BLT that loads data into BB0 (the graphics engine
* always knows the true base). After the BLT, Durango looks to see
* which location changed to know where the base address is.
* - This is a relatively simple way to allow Durango to work on old
* and new platforms without using theCPU_WRITE instructions.
*
* To summarize, the BLT buffers are one of the most painful aspects of
* the GX graphics unit design, and have been removed from future designs
* (the graphics unit has its own dedicated RAM). Durango has tried to
* hide the BLT buffer use from the drivers.
*---------------------------------------------------------------------------
*/
void gu1_detect_blt_buffer_base(void)
{
/* ASSUME 2K */
GFXbb0Base = BB0_BASE_2K;
GFXbb1Base = BB1_BASE_2K;
/* CHECK IF SCRATCHPAD IS SET TO 3K OR 4K */
/* Boot code should still set 3K values for 4K. */
if (gfx_gxm_config_read(GXM_CONFIG_GCR) & 0x08)
{
/* WRITE DATA TO 3K LOCATION */
GFX_WAIT_BUSY;
WRITE_REG32(BB0_BASE_3K, 0xFEEDFACE);
/* HAVE THE GRAPHICS UNIT STORE SOMETHING IN BB0 */
WRITE_REG32(GP_DST_XCOOR, 0x00000000); /* AT (0,0) */
WRITE_REG32(GP_WIDTH, 0x00010004); /* 4x1 BLT */
WRITE_REG16(GP_RASTER_MODE, 0x00AA); /* KEEP DST */
WRITE_REG16(GP_BLIT_MODE, BM_READ_DST_FB0); /* STORE IN BB0 */
/* CHECK 3K LOCATION */
/* Breaks if data happened to be 0xFEEDFACE - unlikely. */
GFX_WAIT_BUSY;
if (READ_REG32(BB0_BASE_3K) != 0xFEEDFACE)
{
GFXbb0Base = BB0_BASE_3K;
GFXbb1Base = BB1_BASE_3K;
}
}
}
/* END OF FILE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -