📄 cim_gp.c
字号:
/* Primitive size is 12 plus the amount of data. */
gp3_cmd_next = gp3_cmd_current + (size_dwords << 2) + 12;
if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
{
gp3_cmd_next = gp3_cmd_top;
gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | GP3_LUT_HDR_DATA_ENABLE;
/* WAIT FOR HARDWARE */
/* Same logic as BLT wrapping. */
GP3_WAIT_WRAP(temp);
}
else
{
gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
/* WAIT FOR AVAILABLE SPACE */
GP3_WAIT_PRIMITIVE(temp);
}
/* SAVE CURRENT BUFFER POINTER */
cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
/* PREPARE FOR COMMAND BUFFER DATA WRITES */
/* Pattern data is contiguous DWORDs at LUT address 0 */
WRITE_COMMAND32 (0, gp3_cmd_header);
WRITE_COMMAND32 (4, 0);
WRITE_COMMAND32 (8, (size_dwords | GP3_LUT_DATA_TYPE));
/* WRITE ALL DATA */
WRITE_COMMAND_STRING32 (12, colors, 0, size_dwords);
/* START OPERATION */
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
gp3_cmd_current = gp3_cmd_next;
}
/*---------------------------------------------------------------------------
* gp_set_vector_pattern
*
* This routine is called to program the hardware LUT with a vector pattern.
* A vector pattern is programmed as a 32-bit mask that specifies a
* transparency pattern. A length parameter is used to specify patterns
* smaller than 32. Note that vectors in Geode LX do not continue across corners.
* The beginning of each vector will always begin with bit 0 of the vector
* pattern. It is the responsibility of the caller to update the pattern
* if an alternate behavior is desired.
*
* This routine faces the same restrictions of all routines that program
* the LUT, in that it must be called before any gp_declare_xxxx routines,
* it cannot be combined with an 8x8 color pattern, color conversion or
* rotation.
*-------------------------------------------------------------------------*/
void gp_set_vector_pattern (unsigned long pattern, unsigned long color, int length)
{
unsigned long temp, mask;
gp3_ch3_pat = 1;
gp3_vector_pattern_color = color;
/* CREATE SUITABLE PATTERN MASK */
/* The GP requires a minimum of four pixels in a vector pattern. We */
/* can get around this restriction by doubling any patterns smaller */
/* than 4 pixels. */
while (length < 4)
{
mask = 0xFFFFFFFF >> (32 - length);
pattern = (pattern << length) | (pattern & mask);
length <<= 1;
}
mask = 0xFFFFFFFF >> (32 - length);
gp3_vec_pat = pattern;
/* CHECK FOR WRAP AFTER LUT LOAD */
gp3_cmd_next = gp3_cmd_current + GP3_VECTOR_PATTERN_COMMAND_SIZE;
if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
{
gp3_cmd_next = gp3_cmd_top;
gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_WRAP | GP3_LUT_HDR_DATA_ENABLE;
/* WAIT FOR HARDWARE */
/* Same logic as BLT wrapping. */
GP3_WAIT_WRAP(temp);
}
else
{
gp3_cmd_header = GP3_LUT_HDR_TYPE | GP3_LUT_HDR_DATA_ENABLE;
/* WAIT FOR AVAILABLE SPACE */
GP3_WAIT_PRIMITIVE(temp);
}
/* SAVE CURRENT BUFFER POINTER */
cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
/* PREPARE FOR COMMAND BUFFER DATA WRITES */
/* Pattern data is 2 DWORDs at 0x100 and 0x101 */
WRITE_COMMAND32 (0, gp3_cmd_header);
WRITE_COMMAND32 (4, 0x100);
WRITE_COMMAND32 (8, (2 | GP3_LUT_DATA_TYPE));
WRITE_COMMAND32 (12, pattern);
WRITE_COMMAND32 (16, mask);
/* START OPERATION */
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
gp3_cmd_current = gp3_cmd_next;
}
/*---------------------------------------------------------------------------
* gp_set_strides
*
* This routine is called to program the pitch between successive lines of
* data in the frame buffer. The strides should be DWORD aligned and less
* than 64K. These restrictions are not checked by the API.
*-------------------------------------------------------------------------*/
void gp_set_strides (unsigned long dst_stride, unsigned long src_stride)
{
/* SAVE STRIDES */
/* The source stride may be needed later for channel 3 source data and */
/* we may need to use these strides in calculations. */
gp3_src_stride = src_stride;
gp3_dst_stride = dst_stride;
/* ENABLE STRIDES */
/* The stride register is in the same place for BLTs and vectors */
gp3_cmd_header |= GP3_BLT_HDR_STRIDE_ENABLE;
WRITE_COMMAND32 (GP3_BLT_STRIDE, ((src_stride << 16) | dst_stride));
}
/*---------------------------------------------------------------------------
* gp_set_source_format
*
* This routine is used to program the format of source data used in subsequent
* color-conversion or rotation operations. Note that 4BPP indexed and 8BPP
* indexed source formats cannot be used when rotating, as the LUT will be
* destroyed. These formats also cannot be combined with an 8x8 color pattern.
* The supported formats mirror the hardware and are described as follows:
*
* 0 - 8BPP 3:3:2
* 1 - 8BPP indexed
* 4 - 16BPP 4:4:4:4
* 5 - 16BPP 1:5:5:5
* 6 - 16BPP 5:6:5
* 7 - 16BPP YUV
* 8 - 32BPP 8:8:8:8
* 13 - 4BPP indexed
* 20 - 16BPP 4:4:4:4 BGR
* 21 - 16BPP 1:5:5:5 BGR
* 22 - 16BPP 0:5:6:5 BGR
* 24 - 32BPP 8:8:8:8 BGR
*-------------------------------------------------------------------------*/
void gp_set_source_format (int format)
{
/* SAVE FORMAT */
/* We will combine the source format later when doing color conversion. */
/* We also save the pixel size for host source calculations. */
/* Conveniently, the source formats are organized such that the upper */
/* two bits of the nibble represent the pixel shift, with a pixel shift */
/* of 3 being a special case for 4BPP data. Clever, yes? Even more */
/* clever, bit 4 indicates BGR ordering. */
gp3_src_pix_shift = (unsigned long)((format >> 2) & 3);
gp3_src_format = (((unsigned long)format & 0xF) << 24) |
(((unsigned long)format & 0x10) << 18);
}
/*---------------------------------------------------------------------------
* gp_pattern_fill
*
* This routine is called to perform a simple pattern fill. The pattern
* can be solid, monochrome or a preprogrammed 8x8 color pattern. If
* the ROP involves source data, that source data will be constant.
*-------------------------------------------------------------------------*/
void gp_pattern_fill (unsigned long dstoffset, unsigned long width, unsigned long height)
{
unsigned long base_register;
base_register = (gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK) |
((gp3_fb_base << 24) + (dstoffset & 0xFFC00000));
/* ENABLE RELEVANT REGISTERS */
/* Note that we always enable and write the channel 3 mode, if only */
/* to turn it off. Cimarron also always writes the base offset */
/* register to allow operation with frame buffers larger than 16MB. */
gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
GP3_BLT_HDR_WIDHI_ENABLE |
GP3_BLT_HDR_BASE_OFFSET_ENABLE |
GP3_BLT_HDR_CH3_STR_ENABLE |
GP3_BLT_HDR_CH3_WIDHI_ENABLE |
GP3_BLT_HDR_BLT_MODE_ENABLE;
/* WRITE THE REGISTERS COMMON TO ALL PATTERN TYPES */
/* The destination base is the frame buffer base plus whatever */
/* 4MB segment we happen to be BLTing to. */
WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, ((width << 16) | height));
WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base_register);
/* CHECK 8X8 COLOR PATTERN CASE */
if (gp3_ch3_pat)
{
/* SET CHANNEL 3 PATTERN ORIGINS */
gp3_cmd_header |= GP3_BLT_HDR_CH3_OFF_ENABLE;
/* INITIALIZE CHANNEL 3 PARAMETERS */
WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, ((width << 16) | height));
WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, gp3_pat_origin);
WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoffset & 0x3FFFFF);
WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, gp3_pat_format);
}
else
{
/* DISABLE CHANNEL 3 AND USE NORMAL PATTERN ORIGINS */
WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, 0);
WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, ((dstoffset & 0x3FFFFF) | gp3_pat_origin));
}
/* START THE BLT */
WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode);
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
gp3_cmd_current = gp3_cmd_next;
}
/*---------------------------------------------------------------------------
* gp_screen_to_screen_blt
*
* This routine is called to perform a BLT from one location inside video
* memory to another location inside video memory. The source and destination
* formats are assumed to be the current BPP. Whenever possible, this routine
* tries to use channel 3 to fetch source data. The BLT flags can affect this
* behavior in the following ways:
* CIMGP_BLTFLAGS_PRES_COLOR_PAT
* A color pattern is being stored in the channel 3 buffer. It is either
* being stored for a later BLT or being combined with the current source
* data. Channel 3 cannot be used to fetch source data or the pattern
* will be overwritten.
* CIMGP_BLTFLAGS_PRES_LUT
* If the first flag is not set, this flag will limit the use of the
* channel 3 buffer to 1K.
*-------------------------------------------------------------------------*/
void gp_screen_to_screen_blt (unsigned long dstoffset, unsigned long srcoffset,
unsigned long width, unsigned long height, int flags)
{
unsigned long base;
unsigned long ch3_flags = 0;
unsigned long blt_mode = gp3_blt_mode;
unsigned long size = ((width << 16) | height);
unsigned long dstbase, srcbase;
/* CALCULATE BASE OFFSETS */
/* We need to set the 4MB aligned base offsets before we add offsets */
/* for negative BLTs. */
srcbase = srcoffset & 0xFFC00000;
dstbase = dstoffset & 0xFFC00000;
srcoffset &= 0x3FFFFF;
dstoffset &= 0x3FFFFF;
/* ADJUST OFFSETS BASED ON FLAGS */
/* We adjust the source and destination offsets to point to the first */
/* byte of the first pixel of the BLT. This routine assumes that the */
/* source and destination regions do not wrap past the end of a 16MB */
/* region. */
if (flags & CIMGP_NEGXDIR)
{
srcoffset += (width << gp3_pix_shift) - 1;
dstoffset += (width << gp3_pix_shift) - 1;
blt_mode |= GP3_BM_NEG_XDIR;
ch3_flags |= GP3_CH3_NEG_XDIR;
}
if (flags & CIMGP_NEGYDIR)
{
srcoffset += (height - 1) * gp3_src_stride;
dstoffset += (height - 1) * gp3_dst_stride;
blt_mode |= GP3_BM_NEG_YDIR;
ch3_flags |= GP3_CH3_NEG_YDIR;
}
/* BRANCH BASED ON CHANNEL 3 */
/* If a color pattern is not being saved or used, channel 3 will */
/* be used to fetch source for maximum throughput. Channel 3 */
/* is not used if transparency or alpha blending is enabled. */
if (!(gp3_blt_flags & CIMGP_BLTFLAGS_PRES_COLOR_PAT) &&
!(gp3_raster_mode & GP3_RM_SRC_TRANS) &&
!(flags & CIMGP_NEGYDIR))
{
base = ((gp3_fb_base << 24) + dstbase) |
((gp3_fb_base << 4) + (srcbase >> 20)) |
(gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
GP3_BLT_HDR_WIDHI_ENABLE |
GP3_BLT_HDR_CH3_STR_ENABLE |
GP3_BLT_HDR_CH3_WIDHI_ENABLE |
GP3_BLT_HDR_CH3_OFF_ENABLE |
GP3_BLT_HDR_BASE_OFFSET_ENABLE |
GP3_BLT_HDR_BLT_MODE_ENABLE;
WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset | gp3_pat_origin));
WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, srcoffset);
WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, size);
WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
GP3_CH3_C3EN |
GP3_CH3_REPLACE_SOURCE |
gp3_ch3_bpp |
gp3_src_stride |
ch3_flags |
((gp3_blt_flags & CIMGP_ENABLE_PREFETCH) << 17) |
((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
}
else
{
/* CALCULATE BASE OFFSET REGISTER */
base = ((gp3_fb_base << 24) + dstbase) |
((gp3_fb_base << 14) + (srcbase >> 10)) |
(gp3_base_register & GP3_BASE_OFFSET_CH3MASK);
/* PROGRAM THE NORMAL SOURCE CHANNEL REGISTERS */
/* We assume that a color pattern is being ROPed with source */
/* data if the pattern type is color and the preserve pattern */
/* was set. */
blt_mode |= GP3_BM_SRC_FB;
gp3_cmd_header |= GP3_BLT_HDR_SRC_OFF_ENABLE |
GP3_BLT_HDR_DST_OFF_ENABLE |
GP3_BLT_HDR_WIDHI_ENABLE |
GP3_BLT_HDR_CH3_WIDHI_ENABLE |
GP3_BLT_HDR_CH3_STR_ENABLE |
GP3_BLT_HDR_CH3_OFF_ENABLE |
GP3_BLT_HDR_BASE_OFFSET_ENABLE |
GP3_BLT_HDR_BLT_MODE_ENABLE;
if (gp3_ch3_pat)
{
WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, gp3_pat_origin);
WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, dstoffset);
WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR, gp3_pat_format | ch3_flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -