📄 cim_gp.c
字号:
/*
* <LIC_AMD_STD>
* Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
* </LIC_AMD_STD>
*
* <CTL_AMD_STD>
* </CTL_AMD_STD>
*
* <DOC_AMD_STD>
* Cimarron graphics processor routines. These routines program the graphics
* hardware using the graphics command buffer.
* </DOC_AMD_STD>
*
*/
/*---------------------*/
/* CIMARRON GP GLOBALS */
/*---------------------*/
CIMARRON_STATIC unsigned long gp3_bpp = 0;
CIMARRON_STATIC unsigned long gp3_ch3_bpp = 0;
CIMARRON_STATIC unsigned long gp3_pat_origin = 0;
CIMARRON_STATIC unsigned long gp3_buffer_lead = 0;
CIMARRON_STATIC unsigned long gp3_cmd_header;
CIMARRON_STATIC unsigned long gp3_cmd_top;
CIMARRON_STATIC unsigned long gp3_cmd_bottom;
CIMARRON_STATIC unsigned long gp3_cmd_current;
CIMARRON_STATIC unsigned long gp3_cmd_next;
CIMARRON_STATIC unsigned long gp3_blt_mode;
CIMARRON_STATIC unsigned long gp3_vec_mode;
CIMARRON_STATIC unsigned long gp3_raster_mode;
CIMARRON_STATIC unsigned long gp3_pix_shift;
CIMARRON_STATIC unsigned long gp3_ch3_pat;
CIMARRON_STATIC unsigned long gp3_blt;
CIMARRON_STATIC unsigned long gp3_blt_flags;
CIMARRON_STATIC unsigned long gp3_src_stride;
CIMARRON_STATIC unsigned long gp3_dst_stride;
CIMARRON_STATIC unsigned long gp3_src_format;
CIMARRON_STATIC unsigned long gp3_src_pix_shift;
CIMARRON_STATIC unsigned long gp3_pat_format;
CIMARRON_STATIC unsigned long gp3_pat_pix_shift;
CIMARRON_STATIC unsigned long gp3_fb_base;
CIMARRON_STATIC unsigned long gp3_vector_pattern_color;
CIMARRON_STATIC unsigned long gp3_scratch_base;
CIMARRON_STATIC unsigned long gp3_base_register;
CIMARRON_STATIC unsigned long gp3_vec_pat;
/*---------------------------------------------------------------------------
* gp_set_limit_on_buffer_lead
*
* This routine is used to specify the maximum number of bytes in the command
* buffer by which software can lead the graphics processor. When declaring
* a BLT with the CIMGP_BLTFLAGS_LIMITBUFFER flag set, Cimarron will wait until
* the command buffer read and write pointers differ by no more than 'lead'
* bytes. This can be useful to limit the time lag possible when creating a
* command buffer full of simple BLT commands.
*-------------------------------------------------------------------------*/
void gp_set_limit_on_buffer_lead (unsigned long lead)
{
gp3_buffer_lead = lead;
}
/*---------------------------------------------------------------------------
* gp_set_command_buffer_base
*
* This routine is used to program the command buffer region in physical
* memory. The command buffer start address must be 1MB aligned. start and
* stop refer to endpoints within the associated 16MB region. Command buffers
* larger than 16MB are not supported.
*-------------------------------------------------------------------------*/
void gp_set_command_buffer_base (unsigned long address, unsigned long start,
unsigned long stop)
{
Q_WORD msr_value;
/* WAIT FOR IDLE */
/* Obviously, we cannot change the command buffer pointer while the GP */
/* is currently fetching commands. */
gp_wait_until_idle();
/* WRITE THE COMMAND BUFFER BASE */
msr_read64 (MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
msr_value.low &= 0xF000FFFF;
msr_value.low |= (address >> 4) & 0x0FFF0000;
msr_write64 (MSR_DEVICE_GEODELX_GP, MSR_GEODELINK_CONFIG, &msr_value);
/* WRITE THE BASE OFFSETS */
/* We also reset the write and read pointers. The hardware will */
/* automatically update the write pointer when the read pointer */
/* is updated to prevent the hardware from getting confused when */
/* initializing a new command buffer. */
WRITE_GP32 (GP3_CMD_TOP, start);
WRITE_GP32 (GP3_CMD_BOT, stop);
WRITE_GP32 (GP3_CMD_READ, start);
/* SAVE THE BASE ADDRESSES */
/* These are used to determine the appropriate wrap point. */
gp3_cmd_current = gp3_cmd_top = start;
gp3_cmd_bottom = stop;
}
/*---------------------------------------------------------------------------
* gp_set_frame_buffer_base
*
* This routine is used to program the base address of the frame buffer in
* physical memory. The frame buffer address must be 16MB aligned. Cimarron
* tracks the base address because the maximum frame buffer size may exceed
* 16MB. Any primitive will thus program the corresponding 16MB region into all
* base offset registers as well as program the offset into the 16MB region.
* The size parameter is provided to allow Cimarron to claim the last 1MB of
* space to be used as a scratch area for workarounds or expanded functionality.
*-------------------------------------------------------------------------*/
void gp_set_frame_buffer_base (unsigned long address, unsigned long size)
{
gp3_scratch_base = size - GP3_SCRATCH_BUFFER_SIZE;
gp3_fb_base = address >> 24;
gp3_base_register = (gp3_fb_base << 24) | (gp3_fb_base << 14) | (gp3_fb_base << 4);
WRITE_GP32 (GP3_BASE_OFFSET, gp3_base_register);
}
/*---------------------------------------------------------------------------
* gp_set_bpp
*
* This routine sets the output BPP of the GP. The BPP used by the GP does
* not have to match the display BPP, but that is usually the case. The
* supported BPP values are as follows:
*
* 8 - palettized 8BPP
* 12 - 4:4:4:4
* 15 - 1:5:5:5
* 16 - 0:5:6:5
* 32 - 8:8:8:8
*-------------------------------------------------------------------------*/
void gp_set_bpp (int bpp)
{
/* STORE BPP */
/* The bpp is not updated until the next call to gp_set_raster_mode. */
/* This allows the gp_set_bpp call to happen outside of a BLT. It */
/* also implies that no registers need be written in this routine. */
switch(bpp)
{
case 8:
gp3_bpp = GP3_RM_BPPFMT_332;
gp3_ch3_bpp = GP3_CH3_SRC_3_3_2;
gp3_pix_shift = 0;
break;
case 12:
gp3_bpp = GP3_RM_BPPFMT_4444;
gp3_ch3_bpp = GP3_CH3_SRC_4_4_4_4;
gp3_pix_shift = 1;
break;
case 15:
gp3_bpp = GP3_RM_BPPFMT_1555;
gp3_ch3_bpp = GP3_CH3_SRC_1_5_5_5;
gp3_pix_shift = 1;
break;
case 16:
gp3_bpp = GP3_RM_BPPFMT_565;
gp3_ch3_bpp = GP3_CH3_SRC_0_5_6_5;
gp3_pix_shift = 1;
break;
case 24:
case 32:
gp3_bpp = GP3_RM_BPPFMT_8888;
gp3_ch3_bpp = GP3_CH3_SRC_8_8_8_8;
gp3_pix_shift = 2;
break;
default:
gp3_bpp = GP3_RM_BPPFMT_332;
gp3_ch3_bpp = GP3_CH3_SRC_3_3_2;
gp3_pix_shift = 0;
break;
}
}
/*---------------------------------------------------------------------------
* gp_declare_blt
*
* This routine is used to prepare for a 2D BLT. Its primary function
* is to verify that enough room is available in the command buffer
* to hold a BLT command. This command can be called multiple times if
* necessary. For example, if a function calls this routine on entry, but
* later realizes that a LUT load command must be executed before the BLT,
* the application could call gp_set_color_pattern and then call
* gp_declare_blt to declare the BLT. This is possible because the hardware
* buffer pointer is not updated until a new BLT is actually executed. An
* application must take care not to call any routines that perform a buffer
* command, (such as gp_set_color_pattern) between gp_declare_blt and the
* routines used to program the BLT parameters. In addition to checking for
* available space, this routine also performs the following actions:
* - Sets the wrap bit if this BLT will pass close to the end of the buffer.
* - Writes the command header.
*
* The available flags are defined as follows:
* 0x01 - Preserve the LUT
* 0x02 - Preserve the color pattern.
* 0x04 - Enable prefetch.
*-------------------------------------------------------------------------*/
void gp_declare_blt (unsigned long flags)
{
unsigned long temp;
gp3_blt = 1;
gp3_blt_flags = flags;
/* SET ADDRESS OF NEXT COMMAND */
/* A summary of the command buffer logic is as follows: */
/* - If after a basic BLT we will not have room for the largest */
/* command (a full line of host source data), we set the wrap */
/* bit. This will waste up to a whopping 8K of command buffer */
/* space, but it simplifies the logic for all commands. */
/* - If we are wrapping, we have extra logic to ensure that we */
/* don't skip over the current GP read pointer. */
gp3_cmd_next = gp3_cmd_current + GP3_BLT_COMMAND_SIZE;
/* CHECK WRAP CONDITION */
if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
{
gp3_cmd_next = gp3_cmd_top;
gp3_cmd_header = GP3_BLT_HDR_TYPE | GP3_BLT_HDR_WRAP;
/* WAIT FOR HARDWARE */
/* When wrapping, we must take steps to ensure that we do not */
/* wrap over the current hardware read pointer. We do this by */
/* verifying that the hardware is not between us and the end of */
/* the command buffer. We also have a special case to make sure */
/* that the hardware is not currently reading the top of the */
/* command buffer. */
GP3_WAIT_WRAP(temp);
}
else
{
gp3_cmd_header = GP3_BLT_HDR_TYPE;
/* WAIT FOR AVAILABLE SPACE */
GP3_WAIT_PRIMITIVE(temp);
}
if (flags & CIMGP_BLTFLAGS_LIMITBUFFER)
{
while (1)
{
temp = READ_GP32 (GP3_CMD_READ);
if (((gp3_cmd_current >= temp) && ((gp3_cmd_current - temp) <= gp3_buffer_lead)) ||
((gp3_cmd_current < temp) && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <= gp3_buffer_lead)))
{
break;
}
}
}
/* SET THE CURRENT BUFFER POINTER */
/* We initialize a pointer to the current buffer base to avoid an */
/* extra addition for every buffer write. */
cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
/* SET THE HAZARD BIT */
if (flags & CIMGP_BLTFLAGS_HAZARD)
gp3_cmd_header |= GP3_BLT_HDR_HAZARD_ENABLE;
}
/*---------------------------------------------------------------------------
* gp_declare_vector
*
* This routine is used to prepare for a 2D vector. It has no other function
* except to verify that enough room is available in the command buffer
* to hold a vector command. The same rules that apply to BLTs apply to
* vectors. (See the documentation for gp_declare_blt).
*-------------------------------------------------------------------------*/
void gp_declare_vector (unsigned long flags)
{
unsigned long temp;
gp3_blt = 0;
gp3_blt_flags = flags;
/* SET ADDRESS OF NEXT COMMAND */
/* The logic to force a wrap during a vector is identical */
/* to the BLT logic. */
/* ALLOCATE SPACE FOR AN ADDITIONAL VECTOR TO CLEAR THE BYTE ENABLES */
gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_COMMAND_SIZE + GP3_VECTOR_COMMAND_SIZE + 32;
/* CHECK WRAP CONDITION */
if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
{
gp3_cmd_next = gp3_cmd_top;
gp3_cmd_header = GP3_VEC_HDR_TYPE | GP3_VEC_HDR_WRAP;
/* CHECK WRAP CONDITION */
GP3_WAIT_WRAP(temp);
}
else
{
gp3_cmd_header = GP3_VEC_HDR_TYPE;
/* WAIT FOR AVAILABLE SPACE */
GP3_WAIT_PRIMITIVE(temp);
gp3_cmd_next -= GP3_VECTOR_COMMAND_SIZE + 32;
}
if (flags & CIMGP_BLTFLAGS_LIMITBUFFER)
{
while (1)
{
temp = READ_GP32 (GP3_CMD_READ);
if (((gp3_cmd_current >= temp) && ((gp3_cmd_current - temp) <= gp3_buffer_lead)) ||
((gp3_cmd_current < temp) && ((gp3_cmd_current + (gp3_cmd_bottom - temp)) <= gp3_buffer_lead)))
{
break;
}
}
}
cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
/* SET THE HAZARD BIT */
if (flags & CIMGP_BLTFLAGS_HAZARD)
gp3_cmd_header |= GP3_VEC_HDR_HAZARD_ENABLE;
}
/*---------------------------------------------------------------------------
* gp_write_parameters
*
* This routine is called to write all recent parameters to the hardware.
* This routine is necessary for any implementation that performs the setup
* for a BLT separate from the actual BLT. An example would be a driver
* that prepares for multiple pattern fills by programming the ROP,
* pattern color and destination stride. The driver might then perform
* repeated pattern fills with minimal effort.
*-------------------------------------------------------------------------*/
void gp_write_parameters (void)
{
/* WRITE THE COMMAND HEADER */
/* Command header is at offset 0 for BLTs and vectors */
WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
/* INCREMENT THE CURRENT WRITE POINTER */
gp3_cmd_current = gp3_cmd_next;
/* UPDATE THE GP WRITE POINTER */
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_current);
}
/*---------------------------------------------------------------------------
* gp_set_raster_operation
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -