📄 cim_gp.c
字号:
if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
{
gp3_cmd_next = gp3_cmd_top;
GP3_WAIT_WRAP(temp);
WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
GP3_DATA_LOAD_HDR_ENABLE);
}
else
{
GP3_WAIT_PRIMITIVE(temp);
WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
}
/* WRITE DWORD COUNT */
WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
while (height--)
{
/* WRITE DATA */
WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
srcoffset + (dword_count << 2), byte_count);
srcoffset += pitch;
cim_cmd_ptr += total_dwords << 2;
}
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
gp3_cmd_current = gp3_cmd_next;
}
else
{
/* WRITE DATA LINE BY LINE */
/* Each line will be created as a separate command buffer entry to allow */
/* line-by-line wrapping and to allow simultaneous rendering by the HW. */
while (height--)
{
/* UPDATE THE COMMAND POINTER */
/* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
/* This is created by adding gp3_cmd_current to the base pointer. */
cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
/* CHECK IF A WRAP WILL BE NEEDED */
gp3_cmd_next = gp3_cmd_current + size_dwords;
if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
{
gp3_cmd_next = gp3_cmd_top;
/* WAIT FOR HARDWARE */
GP3_WAIT_WRAP(temp);
WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
GP3_DATA_LOAD_HDR_ENABLE);
}
else
{
/* WAIT FOR AVAILABLE SPACE */
GP3_WAIT_PRIMITIVE(temp);
WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
}
/* WRITE DWORD COUNT */
WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
/* WRITE DATA */
WRITE_COMMAND_STRING32 (8, data, srcoffset, dword_count);
WRITE_COMMAND_STRING8 (8 + (dword_count << 2), data,
srcoffset + (dword_count << 2), byte_count);
/* UPDATE POINTERS */
srcoffset += pitch;
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
gp3_cmd_current = gp3_cmd_next;
}
}
}
/*---------------------------------------------------------------------------
* gp_custom_convert_blt
*
* This routine is identical to gp_color_convert_blt, except that the macro
* to write data to the frame buffer has been replaced with a new macro. This
* allows a user to implement custom behavior when sending data, such as manually
* converting 24BPP to 32BPP, converting 2BPP to 4BPP or premultiplying alpha data.
*-------------------------------------------------------------------------*/
void gp_custom_convert_blt (unsigned long dstoffset, unsigned long srcx,
unsigned long width, unsigned long height, unsigned char *data, long pitch)
{
unsigned long indent, temp;
unsigned long total_dwords, size_dwords;
unsigned long dword_count, byte_count;
unsigned long size = ((width << 16) | height);
unsigned long ch3_offset, srcoffset;
unsigned long ch3_size, base;
/* ASSUME BITMAPS ARE DWORD ALIGNED */
/* We will offset into the source data in DWORD increments. We */
/* set the source index to the remaining byte offset and */
/* increment the size of each line to account for the dont-care */
/* pixel(s). For 4BPP source data, we also set the appropriate */
/* nibble index. */
/* CALCULATE THE SIZE OF ONE LINE */
if ((gp3_src_format & GP3_CH3_SRC_MASK) == GP3_CH3_SRC_24BPP_PACKED)
{
/* HANDLE 24BPP */
/* Note that we do not do anything to guarantee that the source data */
/* is DWORD aligned. The logic here is that the source data will be */
/* cacheable, in which case Geode LX will not lose any clocks for unaligned */
/* moves. Also note that the channel 3 width is programmed as the */
/* number of dwords, while the normal width is programmed as the number */
/* of pixels. */
srcoffset = srcx * 3;
ch3_offset = 0;
temp = width * 3;
ch3_size = (((temp + 3) >> 2) << 16) | height;
}
else
{
ch3_size = size;
if (gp3_src_pix_shift == 3)
{
/* CALCULATE INDENT AND SOURCE OFFSET */
indent = (srcx >> 1);
srcoffset = (indent & ~3L);
indent &= 3;
ch3_offset = indent | ((srcx & 1) << 25);
temp = ((width + (srcx & 1) + 1) >> 1) + indent;
}
else
{
indent = (srcx << gp3_src_pix_shift);
srcoffset = (indent & ~3L);
indent &= 3;
ch3_offset = indent;
temp = (width << gp3_src_pix_shift) + indent;
}
}
total_dwords = (temp + 3) >> 2;
size_dwords = (total_dwords << 2) + 8;
dword_count = (temp >> 2);
byte_count = (temp & 3);
base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
(gp3_base_register & ~GP3_BASE_OFFSET_DSTMASK);
/* SET APPROPRIATE ENABLES */
gp3_cmd_header |= GP3_BLT_HDR_DST_OFF_ENABLE |
GP3_BLT_HDR_WIDHI_ENABLE |
GP3_BLT_HDR_CH3_STR_ENABLE |
GP3_BLT_HDR_CH3_OFF_ENABLE |
GP3_BLT_HDR_CH3_WIDHI_ENABLE |
GP3_BLT_HDR_BASE_OFFSET_ENABLE |
GP3_BLT_HDR_BLT_MODE_ENABLE;
WRITE_COMMAND32 (GP3_BLT_DST_OFFSET, (dstoffset & 0x3FFFFF) | gp3_pat_origin);
WRITE_COMMAND32 (GP3_BLT_CH3_OFFSET, ch3_offset);
WRITE_COMMAND32 (GP3_BLT_WID_HEIGHT, size);
WRITE_COMMAND32 (GP3_BLT_CH3_WIDHI, ch3_size);
WRITE_COMMAND32 (GP3_BLT_BASE_OFFSET, base);
WRITE_COMMAND32 (GP3_BLT_CH3_MODE_STR,
GP3_CH3_C3EN |
GP3_CH3_REPLACE_SOURCE |
GP3_CH3_HST_SRC_ENABLE |
gp3_src_format |
((gp3_blt_flags & CIMGP_BLTFLAGS_PRES_LUT) << 20));
WRITE_COMMAND32 (GP3_BLT_MODE, gp3_blt_mode);
/* START THE BLT */
WRITE_COMMAND32 (GP3_BLT_CMD_HEADER, gp3_cmd_header);
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
gp3_cmd_current = gp3_cmd_next;
if (((total_dwords << 2) * height) <= GP3_BLT_1PASS_SIZE &&
(gp3_cmd_bottom - gp3_cmd_current) > (GP3_BLT_1PASS_SIZE + 72))
{
/* UPDATE THE COMMAND POINTER */
cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
/* CHECK IF A WRAP WILL BE NEEDED */
gp3_cmd_next = gp3_cmd_current + ((total_dwords << 2) * height) + 8;
if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
{
gp3_cmd_next = gp3_cmd_top;
GP3_WAIT_WRAP(temp);
WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
GP3_DATA_LOAD_HDR_ENABLE);
}
else
{
GP3_WAIT_PRIMITIVE(temp);
WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
}
/* WRITE DWORD COUNT */
WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | (total_dwords * height));
while (height--)
{
/* WRITE DATA */
WRITE_CUSTOM_COMMAND_STRING32 (8, data, srcoffset, dword_count);
WRITE_CUSTOM_COMMAND_STRING8 (8 + (dword_count << 2), data,
srcoffset + (dword_count << 2), byte_count);
srcoffset += pitch;
cim_cmd_ptr += total_dwords << 2;
}
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
gp3_cmd_current = gp3_cmd_next;
}
else
{
/* WRITE DATA LINE BY LINE */
/* Each line will be created as a separate command buffer entry to allow */
/* line-by-line wrapping and to allow simultaneous rendering by the HW. */
while (height--)
{
/* UPDATE THE COMMAND POINTER */
/* The WRITE_COMMANDXX macros use a pointer to the current buffer space. */
/* This is created by adding gp3_cmd_current to the base pointer. */
cim_cmd_ptr = cim_cmd_base_ptr + gp3_cmd_current;
/* CHECK IF A WRAP WILL BE NEEDED */
gp3_cmd_next = gp3_cmd_current + size_dwords;
if ((gp3_cmd_bottom - gp3_cmd_next) <= GP3_MAX_COMMAND_SIZE)
{
gp3_cmd_next = gp3_cmd_top;
/* WAIT FOR HARDWARE */
GP3_WAIT_WRAP(temp);
WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_WRAP |
GP3_DATA_LOAD_HDR_ENABLE);
}
else
{
/* WAIT FOR AVAILABLE SPACE */
GP3_WAIT_PRIMITIVE(temp);
WRITE_COMMAND32 (0, GP3_DATA_LOAD_HDR_TYPE | GP3_DATA_LOAD_HDR_ENABLE);
}
/* WRITE DWORD COUNT */
WRITE_COMMAND32 (4, GP3_CH3_HOST_SOURCE_TYPE | total_dwords);
/* WRITE DATA */
WRITE_CUSTOM_COMMAND_STRING32 (8, data, srcoffset, dword_count);
WRITE_CUSTOM_COMMAND_STRING8 (8 + (dword_count << 2), data,
srcoffset + (dword_count << 2), byte_count);
/* UPDATE POINTERS */
srcoffset += pitch;
WRITE_GP32 (GP3_CMD_WRITE, gp3_cmd_next);
gp3_cmd_current = gp3_cmd_next;
}
}
}
/*---------------------------------------------------------------------------
* gp_rotate_blt
*
* This routine is called to rotate a rectangular area of video memory. The
* data may be color converted during the rotation. 'Degrees' must be a
* multiple of 90 and indicates a clockwise rotation. Width and height
* refer to the width and the height of the source. The output
* destinations will be equal to the rotated dimensions.
*-------------------------------------------------------------------------*/
void gp_rotate_blt (unsigned long dstoffset, unsigned long srcoffset,
unsigned long width, unsigned long height, int degrees)
{
unsigned long sizein, sizeout;
unsigned long ch3_flags;
unsigned long base;
base = ((gp3_fb_base << 24) + (dstoffset & 0xFFC00000)) |
((gp3_fb_base << 4) + ((srcoffset & 0xFFC00000) >> 20)) |
(gp3_base_register & GP3_BASE_OFFSET_SRCMASK);
srcoffset &= 0x3FFFFF;
dstoffset &= 0x3FFFFF;
/* SET ROTATION PARAMETERS */
switch (degrees)
{
case 90:
srcoffset += (height - 1) * gp3_src_stride;
sizein = ((width << 16) | height);
sizeout = ((height << 16) | width);
ch3_flags = GP3_CH3_C3EN |
GP3_CH3_REPLACE_SOURCE |
GP3_CH3_ROTATE_ENABLE |
GP3_CH3_NEG_YDIR;
break;
case 180:
srcoffset += (height - 1) * gp3_src_stride;
srcoffset += (width << gp3_src_pix_shift) - 1;
sizein = sizeout = ((width << 16) | height);
ch3_flags = GP3_CH3_C3EN |
GP3_CH3_REPLACE_SOURCE |
GP3_CH3_NEG_YDIR |
GP3_CH3_NEG_XDIR;
break;
case 270:
srcoffset += (width << gp3_src_pix_shift) - 1;
sizein = ((width << 16) | height);
sizeout = ((height << 16) | width);
ch3_flags = GP3_CH3_C3EN |
GP3_CH3_REPLACE_SOURCE |
GP3_CH3_ROTATE_ENABLE |
GP3_CH3_NEG_XDIR;
break;
default:
sizein = sizeout = ((width << 16) | height);
ch3_flags = GP3_CH3_C3EN |
GP3_CH3_REPLACE_SOURCE;
break;
}
/* SET APPROPRIATE ENABLES */
/* We override the raster mode setting with a source */
/* copy ROP. */
gp3_cmd_header |= GP3_BLT_HDR_RASTER_ENABLE |
GP3_BLT_HDR_DST_OFF_ENABLE |
GP3_BLT_HDR_WIDHI_ENABLE |
GP3_BLT_HDR_CH3_OFF_ENABLE |
GP3_BLT_HDR_CH3_STR_ENABLE |
GP3_BLT_HDR_CH3_WIDHI_ENABLE |
GP3_BLT_HDR_BASE_OFFSET_ENABLE |
GP3_BLT_HDR_BLT_MODE_ENABLE;
/* WRITE ALL BLT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -