📄 cim_vg.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 display controller routines. These routines program the display
* mode and configure the hardware cursor and video buffers.
* </DOC_AMD_STD>
*
*/
/*---------------------*/
/* CIMARRON VG GLOBALS */
/*---------------------*/
CIMARRON_STATIC unsigned long vg3_x_hotspot = 0;
CIMARRON_STATIC unsigned long vg3_y_hotspot = 0;
CIMARRON_STATIC unsigned long vg3_cursor_offset = 0;
CIMARRON_STATIC unsigned long vg3_mode_width = 0;
CIMARRON_STATIC unsigned long vg3_mode_height = 0;
CIMARRON_STATIC unsigned long vg3_panel_width = 0;
CIMARRON_STATIC unsigned long vg3_panel_height = 0;
CIMARRON_STATIC unsigned long vg3_delta_x = 0;
CIMARRON_STATIC unsigned long vg3_delta_y = 0;
CIMARRON_STATIC unsigned long vg3_bpp = 0;
CIMARRON_STATIC unsigned long vg3_color_cursor = 0;
CIMARRON_STATIC unsigned long vg3_panel_enable = 0;
/*---------------------------------------------------------------------------
* vg_delay_milliseconds
*
* This routine delays for a number of milliseconds based on a crude
* delay loop.
*---------------------------------------------------------------------------*/
int vg_delay_milliseconds (unsigned long ms)
{
/* ASSUME 500 MHZ 20 CLOCKS PER READ */
unsigned long loop = ms * 25000;
while (loop-- > 0)
{
READ_REG32 (DC3_UNLOCK);
}
return CIM_STATUS_OK;
}
/*---------------------------------------------------------------------------
* vg_set_display_mode
*
* This routine sets a CRT display mode using predefined Cimarron timings. The
* source width and height are specified to allow scaling.
*---------------------------------------------------------------------------*/
int vg_set_display_mode (unsigned long src_width, unsigned long src_height,
unsigned long dst_width, unsigned long dst_height, int bpp, int hz,
unsigned long flags)
{
VG_QUERY_MODE crt_query;
VG_DISPLAY_MODE crt_mode;
int mode;
crt_query.active_width = dst_width;
crt_query.active_height = dst_height;
crt_query.bpp = bpp;
crt_query.hz = hz;
crt_query.query_flags = VG_QUERYFLAG_ACTIVEWIDTH |
VG_QUERYFLAG_ACTIVEHEIGHT |
VG_QUERYFLAG_BPP |
VG_QUERYFLAG_REFRESH;
mode = vg_get_display_mode_index (&crt_query);
if (mode >= 0)
{
crt_mode = CimarronDisplayModes[mode];
crt_mode.src_width = src_width;
crt_mode.src_height = src_height;
/* ADD USER-REQUESTED FLAGS */
crt_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS);
if (flags & VG_MODEFLAG_OVERRIDE_BAND)
{
crt_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK;
crt_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK);
}
if (flags & VG_MODEFLAG_INT_OVERRIDE)
{
crt_mode.flags &= ~VG_MODEFLAG_INT_MASK;
crt_mode.flags |= (flags & VG_MODEFLAG_INT_MASK);
}
return vg_set_custom_mode (&crt_mode, bpp);
}
return CIM_STATUS_ERROR;
}
/*---------------------------------------------------------------------------
* vg_set_panel_mode
*
* This routine sets a panel mode using predefined Cimarron fixed timings. The
* source width and height specify the width and height of the data in the frame
* buffer. The destination width and height specify the width and height of
* the active data to be displayed. The panel width and height specify the
* dimensions of the panel. This interface allows the user to scale or center
* graphics data or both. To perform scaling, the src width or height should
* be different than the destination width or height. To perform centering or
* panning, the destination width and height should be different than the panel
* resolution.
*---------------------------------------------------------------------------*/
int vg_set_panel_mode (unsigned long src_width, unsigned long src_height,
unsigned long dst_width, unsigned long dst_height,
unsigned long panel_width, unsigned long panel_height,
int bpp, unsigned long flags)
{
unsigned long sync_width;
unsigned long sync_offset;
VG_QUERY_MODE panel_query;
VG_DISPLAY_MODE panel_mode;
int mode;
/* SEARCH CIMARRON'S TABLE OF PREDEFINED PANEL MODES */
/* If the destination resolution is larger than the panel resolution, */
/* panning will be performed. However, the timings for a panned mode */
/* are identical to the timings without panning. To save space in the */
/* mode tables, there are no additional table entries for modes with */
/* panning. Instead, we read the timings for a mode without panning */
/* and override the structure entries that specify the width and */
/* height of the mode. We perform a similar procedure for centered */
/* modes, except that certain timing parameters are dynamically */
/* calculated. */
panel_query.active_width = panel_width;
panel_query.active_height = panel_height;
panel_query.panel_width = panel_width;
panel_query.panel_height = panel_height;
panel_query.bpp = bpp;
panel_query.query_flags = VG_QUERYFLAG_ACTIVEWIDTH |
VG_QUERYFLAG_ACTIVEHEIGHT |
VG_QUERYFLAG_PANELWIDTH |
VG_QUERYFLAG_PANELHEIGHT |
VG_QUERYFLAG_PANEL |
VG_QUERYFLAG_BPP;
mode = vg_get_display_mode_index (&panel_query);
/* COPY THE DATA FROM THE MODE TABLE TO A TEMPORARY STRUCTURE */
if (mode >= 0)
{
panel_mode = CimarronDisplayModes[mode];
panel_mode.mode_width = dst_width;
panel_mode.mode_height = dst_height;
panel_mode.src_width = src_width;
panel_mode.src_height = src_height;
/* ADD USER-REQUESTED FLAGS */
panel_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS);
if (flags & VG_MODEFLAG_OVERRIDE_BAND)
{
panel_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK;
panel_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK);
}
if (flags & VG_MODEFLAG_INT_OVERRIDE)
{
panel_mode.flags &= ~VG_MODEFLAG_INT_MASK;
panel_mode.flags |= (flags & VG_MODEFLAG_INT_MASK);
}
/* DYNAMICALLY CALCULATE CENTERED TIMINGS */
/* For centered timings the blank start and blank end are set to */
/* half the difference between the mode dimension and the panel */
/* dimension. The sync pulse preserves the width and offset from */
/* blanking whenever possible. */
if (dst_width < panel_width)
{
sync_width = panel_mode.hsyncend - panel_mode.hsyncstart;
sync_offset = panel_mode.hsyncstart - panel_mode.hblankstart;
panel_mode.hactive = dst_width;
panel_mode.hblankstart = panel_mode.hactive + ((panel_width - dst_width) >> 1);
panel_mode.hblankend = panel_mode.htotal - ((panel_width - dst_width) >> 1);
panel_mode.hsyncstart = panel_mode.hblankstart + sync_offset;
panel_mode.hsyncend = panel_mode.hsyncstart + sync_width;
panel_mode.flags |= VG_MODEFLAG_CENTERED;
}
if (dst_height < panel_height)
{
sync_width = panel_mode.vsyncend - panel_mode.vsyncstart;
sync_offset = panel_mode.vsyncstart - panel_mode.vblankstart;
panel_mode.vactive = dst_height;
panel_mode.vblankstart = panel_mode.vactive + ((panel_height - dst_height) >> 1);
panel_mode.vblankend = panel_mode.vtotal - ((panel_height - dst_height) >> 1);
panel_mode.vsyncstart = panel_mode.vblankstart + sync_offset;
panel_mode.vsyncend = panel_mode.vsyncstart + sync_width;
panel_mode.flags |= VG_MODEFLAG_CENTERED;
}
return vg_set_custom_mode (&panel_mode, bpp);
}
return CIM_STATUS_ERROR;
}
/*---------------------------------------------------------------------------
* vg_set_tv_mode
*
* This routine sets a TV display mode using predefined Cimarron timings. The
* source width and height are specified to allow scaling.
*---------------------------------------------------------------------------*/
int vg_set_tv_mode (unsigned long *src_width, unsigned long *src_height,
unsigned long encoder, unsigned long tvres, int bpp, unsigned long flags,
unsigned long h_overscan, unsigned long v_overscan)
{
unsigned long sync_width;
unsigned long sync_offset;
VG_QUERY_MODE tv_query;
VG_DISPLAY_MODE tv_mode;
int mode;
if (!src_width || !src_height)
return CIM_STATUS_INVALIDPARAMS;
tv_query.bpp = bpp;
tv_query.encoder = encoder;
tv_query.tvmode = tvres;
tv_query.query_flags = VG_QUERYFLAG_BPP |
VG_QUERYFLAG_TVOUT |
VG_QUERYFLAG_ENCODER |
VG_QUERYFLAG_TVMODE;
mode = vg_get_display_mode_index (&tv_query);
if (mode >= 0)
{
/* RETRIEVE THE UNSCALED RESOLUTION */
/* As we are indexing here simply by a mode and encoder, the actual */
/* timings may vary. A 0 value for source or height will thus query the */
/* unscaled resolution. */
if (!(*src_width) || !(*src_height))
{
*src_width = CimarronDisplayModes[mode].hactive - (h_overscan << 1);
*src_height = CimarronDisplayModes[mode].vactive;
if (CimarronDisplayModes[mode].flags & VG_MODEFLAG_INTERLACED)
{
if (((flags & VG_MODEFLAG_INT_OVERRIDE) &&
(flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_LINEDOUBLE) ||
(!(flags & VG_MODEFLAG_INT_OVERRIDE) &&
(CimarronDisplayModes[mode].flags & VG_MODEFLAG_INT_MASK) == VG_MODEFLAG_INT_LINEDOUBLE))
{
if (CimarronDisplayModes[mode].vactive_even > CimarronDisplayModes[mode].vactive)
*src_height = CimarronDisplayModes[mode].vactive_even;
/* ONLY 1/2 THE OVERSCAN FOR LINE DOUBLED MODES */
*src_height -= v_overscan;
}
else
{
*src_height += CimarronDisplayModes[mode].vactive_even;
*src_height -= v_overscan << 1;
}
}
else
{
*src_height -= v_overscan << 1;
}
return CIM_STATUS_OK;
}
tv_mode = CimarronDisplayModes[mode];
tv_mode.src_width = *src_width;
tv_mode.src_height = *src_height;
/* ADD USER-REQUESTED FLAGS */
tv_mode.flags |= (flags & VG_MODEFLAG_VALIDUSERFLAGS);
if (flags & VG_MODEFLAG_OVERRIDE_BAND)
{
tv_mode.flags &= ~VG_MODEFLAG_BANDWIDTHMASK;
tv_mode.flags |= (flags & VG_MODEFLAG_BANDWIDTHMASK);
}
if (flags & VG_MODEFLAG_INT_OVERRIDE)
{
tv_mode.flags &= ~VG_MODEFLAG_INT_MASK;
tv_mode.flags |= (flags & VG_MODEFLAG_INT_MASK);
}
/* ADJUST FOR OVERSCAN */
if (h_overscan)
{
sync_width = tv_mode.hsyncend - tv_mode.hsyncstart;
sync_offset = tv_mode.hsyncstart - tv_mode.hblankstart;
tv_mode.hactive -= h_overscan << 1;
tv_mode.hblankstart = tv_mode.hactive + h_overscan;
tv_mode.hblankend = tv_mode.htotal - h_overscan;
tv_mode.hsyncstart = tv_mode.hblankstart + sync_offset;
tv_mode.hsyncend = tv_mode.hsyncstart + sync_width;
tv_mode.flags |= VG_MODEFLAG_CENTERED;
}
if (v_overscan)
{
sync_width = tv_mode.vsyncend - tv_mode.vsyncstart;
sync_offset = tv_mode.vsyncstart - tv_mode.vblankstart;
if (tv_mode.flags & VG_MODEFLAG_INTERLACED)
{
tv_mode.vactive -= v_overscan;
tv_mode.vblankstart = tv_mode.vactive + (v_overscan >> 1);
tv_mode.vblankend = tv_mode.vtotal - (v_overscan >> 1);
tv_mode.vsyncstart = tv_mode.vblankstart + sync_offset;
tv_mode.vsyncend = tv_mode.vsyncstart + sync_width;
sync_width = tv_mode.vsyncend_even - tv_mode.vsyncstart_even;
sync_offset = tv_mode.vsyncstart_even - tv_mode.vblankstart_even;
tv_mode.vactive_even -= v_overscan;
tv_mode.vblankstart_even = tv_mode.vactive_even + (v_overscan >> 1);
tv_mode.vblankend_even = tv_mode.vtotal_even - (v_overscan >> 1);
tv_mode.vsyncstart_even = tv_mode.vblankstart_even + sync_offset;
tv_mode.vsyncend_even = tv_mode.vsyncstart_even + sync_width;
}
else
{
tv_mode.vactive -= v_overscan << 1;
tv_mode.vblankstart = tv_mode.vactive + v_overscan;
tv_mode.vblankend = tv_mode.vtotal - v_overscan;
tv_mode.vsyncstart = tv_mode.vblankstart + sync_offset;
tv_mode.vsyncend = tv_mode.vsyncstart + sync_width;
}
tv_mode.flags |= VG_MODEFLAG_CENTERED;
}
/* TV MODES WILL NEVER ALLOW PANNING */
tv_mode.panel_width = tv_mode.hactive;
tv_mode.panel_height = tv_mode.vactive;
tv_mode.mode_width = tv_mode.hactive;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -