📄 mae_be.c
字号:
#include "mae_global.h"
#include "mae_be.h"
#include "queue.h"
#include "mae_memory.h"
#include <windows.h>
#define LUTSIZE 32
// It was found that (with some WMV cert clips) when the encoded height is 496 (and when we
// scale it down to 480 for display) the MAE-BE would fail to generate an interruput. The
// problem was with the VSR not getting programmed with the right fractional value. (Also
// the issue could be reproduced across codecs). Defining ADJUST_HV_RATIO_ALWAYS fixes that.
#define ADJUST_HV_RATIO_ALWAYS
extern AU1200_LCD lcd_info;
extern UINT32 video_out_rotation; // default, no rotation
RECT g_RectPlayer;
RECT g_RectScreen;
UINT32 csc_matrix[12] =
{
0x04a7, 0x0000, 0x0662,
0x04a7, 0x1191, 0x1340,
0x04a7, 0x0811, 0x0000,
0xf211, 0x0879, 0xeeb3
};
UINT32 glut[LUTSIZE] =
{
0x00033a03, 0x00043903, 0x00053902, 0x00063802,
0x00073801, 0x00083701, 0x00093601, 0x000b3401,
0x000c3400, 0x000e3200, 0x000f3100, 0x00112f00,
0x00132d00, 0x00162a00, 0x00182800, 0x001a2600,
0x001d2300, 0x001f2100, 0x00211f00, 0x00241c00,
0x00261a00, 0x00291700, 0x002b1500, 0x002d1300,
0x00301000, 0x01320d00, 0x01330c00, 0x01350a00,
0x01360900, 0x02370700, 0x02380600, 0x03380500
};
void program_static_be_registers(void)
{
UINT32 reg;
UINT32 i;
program_lut();
// CSC
for (i=0, reg=MAEBE_CSCMATRIX; i<12; i++, reg+=4)
{
au_writel(csc_matrix[i], reg);
}
// Use the alpha plane for 32 BPP
if ((SIZE_RGB_BPP == 32) || (SIZE_RGB_BPP == 24))
{
au_writel(0xFF, MAEBE_CSCALPHA);
}
else
{
au_writel(0, MAEBE_CSCALPHA);
}
}
void dump_lcd_registers(void)
{
DPRINTF(MSG_BE, (TEXT("backcolor\t%08X\n"), lcd->backcolor));
DPRINTF(MSG_BE, (TEXT("ColorKey\t%08X\tmask\t%08X\n"), lcd->colorkey, lcd->colorkeymsk));
DPRINTF(MSG_BE, (TEXT("Alpha \t%d \t%d\n"),
((lcd->window[0].winctrl0 >> 2) & 0x1ff), ((lcd->window[MAE_PLANE].winctrl0 >> 2) & 0x1ff)));
DPRINTF(MSG_BE, (TEXT("Plane alpha override\t%d \t%d\n"),
((lcd->window[0].winctrl0 >> 1) & 0x1), ((lcd->window[MAE_PLANE].winctrl0 >> 1) & 0x1)));
DPRINTF(MSG_BE, (TEXT("priority \t%d \t%d\n"),
(lcd->window[0].winctrl1 >> 30), (lcd->window[MAE_PLANE].winctrl1 >> 30)));
DPRINTF(MSG_BE, (TEXT("channel \t%d \t%d\n"),
((lcd->window[0].winctrl1 >> 29) & 0x1), ((lcd->window[MAE_PLANE].winctrl1 >> 29) & 0x1)));
DPRINTF(MSG_BE, (TEXT("Xsiz \t%d \t%d \n"),
((lcd->window[0].winctrl1 >> 11) & 0x7ff), ((lcd->window[MAE_PLANE].winctrl1 >> 11) & 0x7ff)));
DPRINTF(MSG_BE, (TEXT("Ysiz \t%d \t%d\n"),
((lcd->window[0].winctrl1) & 0x7ff), ((lcd->window[MAE_PLANE].winctrl1) & 0x7ff)));
DPRINTF(MSG_BE, (TEXT("format \t%d \t%d \n"),
((lcd->window[0].winctrl1 >> 25) & 0xF), ((lcd->window[MAE_PLANE].winctrl1 >> 25) & 0xF)));
DPRINTF(MSG_BE, (TEXT("cco\t\t%d \t%d \n"),
((lcd->window[0].winctrl1 >> 24) & 0x1), ((lcd->window[MAE_PLANE].winctrl1 >> 24) & 0x1)));
DPRINTF(MSG_BE, (TEXT("pixel order\t%d \t%d\n"),
((lcd->window[0].winctrl1 >> 22) & 0x3), ((lcd->window[MAE_PLANE].winctrl1 >> 22) & 0x3)));
DPRINTF(MSG_BE, (TEXT("keymode \t%d \t%d\n"),
((lcd->window[0].winctrl2 >> 24) & 0x3), ((lcd->window[MAE_PLANE].winctrl2 >> 24) & 0x3)));
}
void dump_be_registers(void) {
DPRINTF(MSG_BE, (TEXT("MAEBE_SRCASTR \t%d\n"), au_readl(MAEBE_SRCASTR)));
DPRINTF(MSG_BE, (TEXT("MAEBE_SRCBSTR \t%d\n"), au_readl(MAEBE_SRCBSTR)));
DPRINTF(MSG_BE, (TEXT("MAEBE_SRCCSTR \t%d\n"), au_readl(MAEBE_SRCCSTR)));
DPRINTF(MSG_BE, (TEXT("MAEBE_SRCFHW \t%08X, %d x %d\n"),
au_readl(MAEBE_SRCFHW), au_readl(MAEBE_SRCFHW) & 0x7FF, au_readl(MAEBE_SRCFHW) >> 16));
DPRINTF(MSG_BE, (TEXT("MAEBE_SRCCFG \t%08X\n"), au_readl(MAEBE_SRCCFG)));
DPRINTF(MSG_BE, (TEXT("MAEBE_DSTCFG \t%08X, OF %d\n"),
au_readl(MAEBE_DSTCFG), (au_readl(MAEBE_DSTCFG) >> 2) & 0x3));
DPRINTF(MSG_BE, (TEXT("MAEBE_DSTSTR \t%d bytes\n"), au_readl(MAEBE_DSTSTR)));
DPRINTF(MSG_BE, (TEXT("MAEBE_DSTHEIGHT \t%d lines\n"), au_readl(MAEBE_DSTHEIGHT)));
DPRINTF(MSG_BE, (TEXT("MAEBE_SCFHSR \t%08X\n"), au_readl(MAEBE_SCFHSR)));
DPRINTF(MSG_BE, (TEXT("MAEBE_SCFVSR \t%08X\n"), au_readl(MAEBE_SCFVSR)));
}
void ring_be_doorbell(void)
{
au_writel(MAEBE_CTLFPC_START, MAEBE_CTLFPC);
}
void program_be_regs(PMAEQ_T pmaeq, PRGBQ_T prgbq)
{
//reads overlay hardware, setups mae backend destination
UINT32 yy, uu, vv;
UINT32 hsr, vsr, rgb,iSourceFrameWidth, iSourceFrameHeight;
static UINT32 prev_width=0, prev_height=0;
RECT RectCrop;
UINT32 bytespp;
DPRINTF(MSG_FUNCTION, (TEXT("program_be_regs entry\n")));
// read the current window settings (ddraw changes these through user events)
prgbq->x = ((lcd->window[MAE_PLANE].winctrl0 >> 21) & 0x7ff);
prgbq->y = ((lcd->window[MAE_PLANE].winctrl0 >> 10) & 0x7ff);
prgbq->w = ((lcd->window[MAE_PLANE].winctrl1 >> 11) & 0x7ff) + 1;
prgbq->h = ((lcd->window[MAE_PLANE].winctrl1) & 0x7ff) + 1;
if ((prgbq->w != prev_width) || (prgbq->h != prev_height))
{
prev_width = prgbq->w;
prev_height = prgbq->h;
DPRINTF(MSG_BE, (TEXT("program_be_regs: overlay window %dx%d @ (%d,%d)\n"),
prgbq->w, prgbq->h, prgbq->x, prgbq->y));
#if (MSG_BE == 1)
dump_lcd_registers();
#endif
}
DPRINTF(MSG_BE, (TEXT("program_be_regs: pmaeq->y %x\n"),pmaeq->y));
yy = MAE_PADDR((UINT32)pmaeq->y);
uu = MAE_PADDR((UINT32)pmaeq->u);
vv = MAE_PADDR((UINT32)pmaeq->v);
// Check if the decoder(s) set this field. If so, its asking to chop off
// portions of the right edge of the frame. If not, use the default
if (pmaeq->chopped_picture_linesize)
iSourceFrameWidth = pmaeq->chopped_picture_linesize;
else
iSourceFrameWidth = pmaeq->encoded_picture_linesize;
// Check if the decoder(s) set this field. If so, its asking to chop off
// portions of the bottom edge of the frame. If not, use the default
if (pmaeq->chopped_picture_height)
iSourceFrameHeight = pmaeq->chopped_picture_height;
else
iSourceFrameHeight = pmaeq->encoded_picture_height;
// crop the source image
RectCrop.left = 0;
RectCrop.top = 0;
RectCrop.right = iSourceFrameWidth;
RectCrop.bottom = iSourceFrameHeight;
if (g_RectPlayer.right > g_RectScreen.right)
{
RectCrop.right = (iSourceFrameWidth *
(g_RectScreen.right-g_RectPlayer.left) /
(g_RectPlayer.right-g_RectPlayer.left)) & 0x7F0;
}
if (g_RectPlayer.bottom > g_RectScreen.bottom)
{
RectCrop.bottom = (iSourceFrameHeight *
(g_RectScreen.bottom-g_RectPlayer.top) /
(g_RectPlayer.bottom-g_RectPlayer.top)) & 0x7F0;
}
if ((int)g_RectPlayer.left < (int)g_RectScreen.left)
{
RectCrop.left = (iSourceFrameWidth *
(g_RectScreen.left-g_RectPlayer.left) /
(g_RectPlayer.right-g_RectPlayer.left) + 15) & 0x7F0;
yy += RectCrop.left;
uu += RectCrop.left/2;
vv += RectCrop.left/2;
}
if ((int)g_RectPlayer.top < (int)g_RectScreen.top)
{
RectCrop.top =
(iSourceFrameHeight *
(g_RectScreen.top-g_RectPlayer.top) /
(g_RectPlayer.bottom-g_RectPlayer.top) + 15) & 0x7F0;
yy += RectCrop.top*pmaeq->encoded_picture_linesize;
uu += RectCrop.top*pmaeq->encoded_picture_linesize/2;
vv += RectCrop.top*pmaeq->encoded_picture_linesize/2;
}
DPRINTF(MSG_BE, (TEXT("iSourceFrame %dx%d ovly %d,%d->%d,%d player %d,%d->%d,%d crop %d,%d->%d,%d\n"),
iSourceFrameWidth, iSourceFrameHeight,
prgbq->x, prgbq->y, (prgbq->x+prgbq->w), (prgbq->y+prgbq->h),
g_RectPlayer.left,g_RectPlayer.top,g_RectPlayer.right,g_RectPlayer.bottom,
RectCrop.left,RectCrop.top,RectCrop.right,RectCrop.bottom));
iSourceFrameWidth = (RectCrop.right-RectCrop.left);
iSourceFrameHeight = (RectCrop.bottom-RectCrop.top);
au_writel(((iSourceFrameHeight << 16) | iSourceFrameWidth),MAEBE_SRCFHW);
au_writel(0, MAEBE_SRCCFG); // Use Big Endian format
// BE source registers
au_writel(yy, MAEBE_SRCAADDR);
au_writel(uu, MAEBE_SRCBADDR);
au_writel(vv, MAEBE_SRCCADDR);
// set the strides to be the true FE output size
au_writel(pmaeq->encoded_picture_linesize, MAEBE_SRCASTR);
au_writel(pmaeq->encoded_picture_linesize/2, MAEBE_SRCBSTR);
au_writel(pmaeq->encoded_picture_linesize/2, MAEBE_SRCCSTR);
// BE destination registers
if ((SIZE_RGB_BPP == 32) || (SIZE_RGB_BPP == 24))
{
bytespp = 4;
au_writel(MAEBE_DSTCFG_888A | (video_out_rotation << 5), MAEBE_DSTCFG); // use big endian format
}
else
{
bytespp = 2;
au_writel(MAEBE_DSTCFG_565 | (video_out_rotation << 5), MAEBE_DSTCFG); // use big endian format
}
rgb = MAE_PADDR((UINT32)pmaeq->rgb);
if (video_out_rotation == 0x1)
rgb += (prgbq->w - 8) * bytespp;
else if (video_out_rotation == 0x2)
rgb += prgbq->w * bytespp * prgbq->h -
(((20 * bytespp * prgbq->w) / iSourceFrameWidth) & (~(bytespp - 1)));
else if (video_out_rotation == 0x3)
rgb += prgbq->w * bytespp * (prgbq->h - 1);
au_writel(rgb , MAEBE_DSTADDR);
au_writel(prgbq->w*bytespp, MAEBE_DSTSTR);
if ((video_out_rotation & 0x1))
{
au_writel(prgbq->w, MAEBE_DSTHEIGHT);
hsr = iSourceFrameWidth * 65536 / prgbq->h;
vsr = iSourceFrameHeight * 65536 / prgbq->w;
}
else
{
au_writel(prgbq->h, MAEBE_DSTHEIGHT);
hsr = iSourceFrameWidth * 65536 / prgbq->w;
vsr = iSourceFrameHeight * 65536 / prgbq->h;
}
DPRINTF(MSG_BE, (TEXT("ratios width %d / %d height %d / %d \n"),
iSourceFrameWidth, prgbq->w, iSourceFrameHeight, prgbq->h));
DPRINTF(MSG_BE, (TEXT("program_be_regs: aspect %d : %d\n"),
(pmaeq->aspect >> 16), (pmaeq->aspect & 0xffff)));
DPRINTF(MSG_BE, (TEXT("program_be_regs: hsr 0x%x, vsr 0x%x\n"), hsr, vsr));
#ifndef ADJUST_HV_RATIO_ALWAYS
if (hsr & 0x7)
#endif
{
hsr = (hsr & 0xfffffff8) + 0x8;
}
#ifndef ADJUST_HV_RATIO_ALWAYS
if (vsr & 0x7)
#endif
{
vsr = (vsr & 0xfffffff8) + 0x8;
}
DPRINTF(MSG_BE, (TEXT("program_be_regs: picture %dx%d, chopped %dx%d, BE-input %dx%d, BE-output %dx%d\n"),
pmaeq->encoded_picture_linesize, pmaeq->encoded_picture_height,
pmaeq->chopped_picture_linesize, pmaeq->chopped_picture_height,
iSourceFrameWidth, iSourceFrameHeight, prgbq->w, prgbq->h));
au_writel(hsr, MAEBE_SCFHSR);
au_writel(vsr, MAEBE_SCFVSR);
au_writel(0, MAEBE_SCFDISABLE); // enable the scf, set to 1 to bypass
#if (MSG_BE == 1)
dump_be_registers();
#endif
}
// search within the queued BE elements to find the next BE element to process in display order
PMAEQ_T get_next_temporal_element(void)
{
unsigned char chosen=FALSE;
PMAEQ_T p,q;
DPRINTF(MSG_FUNCTION, (TEXT("get_next_temporal_element Entry\n")));
p = pmms->be_proc;
// pass over anchor frames that have been displayed but are not yet discarded
q=p;
do {
if (!q->sent_to_be) {
p = q;
chosen=TRUE;
}
q=q->next;
} while ((q!=p) && !chosen);
if (!chosen)
return NULL;
// now search the list for the next temporal frame
for (q = pmms->be_proc->next; q != pmms->be_proc; q=q->next)
{
if ((q->tnum < p->tnum) && (!q->sent_to_be))
p = q;
}
return p;
}
unsigned char run_be_hw(void)
{
PMAEQ_T pmaeq;
PRGBQ_T prgbq;
DPRINTF(MSG_FUNCTION, (TEXT("run_be_hw entry\n")));
DPRINTF(MSG_BE, (TEXT("run_be_hw() pmms->state 0x%x\n"),pmms->state));
// if there is no source or destination then bail
if (!pmms->be_proc) {
pmms->state &= (~ENABLE_BE);
DPRINTF(MSG_BE, (TEXT("run_be_hw: no source or destination !!!\n")));
return FALSE;
}
if (!(pmaeq = get_next_temporal_element())) {
pmms->state &= (~ENABLE_BE);
DPRINTF(MSG_BE, (TEXT("run_be_hw: no temp el !!!\n")));
return FALSE;
}
#ifdef MAE_DUMP
sprintf(pmms->pDumpPtr->szDumpStr[pmms->pDumpPtr->numEntries++], "run_be_hw: frame # %d\n",pmaeq->tnum);
#endif
DPRINTF(MSG_BE, (TEXT("run_be_hw() pmms->state 0x%x\n"),pmms->state));
if (!pmms->rgb_free) {
DPRINTF(MSG_ERROR, (TEXT("run_be_hw: no rgb buffer ????\n")));
}
// attach a new rgb buffer
DLCL_POP(RGBQ_T, &pmms->rgb_free, prgbq);
pmaeq->rgb = prgbq->addr; // assign the static rgb buffer associated with this rgbq
pmaeq->sent_to_be = TRUE; // tell the world this entry has made it to the be
// UNNECESSARY??
prgbq->ready_to_display = FALSE; // we are only beginning to fill the rgb buffer
if(previous_pts > pmaeq->pts)
{
//DBGPRINT(WARNINGS,"run_be_hw(): current tnum %d, pts %d earlier than previous pts %d\n",
// pmaeq->tnum, (int)pmaeq->pts, (int)previous_pts); // KK - avsync
}
previous_pts = prgbq->pts = pmaeq->pts;
prgbq->dts = pmaeq->dts;
prgbq->tnum = pmaeq->tnum;
DLCL_APPEND(RGBQ_T, &pmms->rgb_write, prgbq);
pmms->be_proc = pmaeq; // move the ptr to the one we will now process
// unnecessary
#if 0
if (pmaeq->anchor_flag)
{
prgbq->start_time = 0;
}
else
{
prgbq->start_time = 1;
}
#endif
// PROGRAM THE BE REGISTERS
program_be_regs(pmaeq, prgbq);
DPRINTF(MSG_BE, (TEXT("PROGRAM BE: %d pts %d\n"),pmaeq->tnum, prgbq->pts));
return TRUE;
}
UINT32 init_rgbq_list(void)
{
UINT32 i=0;
PRGBQ_T el;
UINT32 queue_addr = KRNL_RGBQ;
UINT32 rgb_buffer_addr = KRNL_RGB_FRAMES_BASE;
// create free list
while (i<NUM_RGBQ_ELEMENTS)
{
el = (PRGBQ_T)queue_addr;
el->addr = (PUINT32)rgb_buffer_addr;
DLCL_APPEND(RGBQ_T, &pmms->rgb_free, el);
queue_addr += sizeof(RGBQ_T);
rgb_buffer_addr += SIZE_RGB_FRAME;
i++;
}
return 0;
}
void program_lut(void)
{
unsigned long halut, valut;
unsigned long hblut, vblut;
unsigned long hclut, vclut;
unsigned long val, i;
halut = (unsigned long)MAEBE_SCFHALUT;
valut = (unsigned long)MAEBE_SCFVALUT;
hblut = (unsigned long)MAEBE_SCFHBLUT;
vblut = (unsigned long)MAEBE_SCFVBLUT;
hclut = (unsigned long)MAEBE_SCFHCLUT;
vclut = (unsigned long)MAEBE_SCFVCLUT;
for (i=0; i< LUTSIZE; i++)
{
val = glut[i];
//val = 0x00004000; // PPKK - forced to passthrough
au_writel(val, (halut + i*4));
au_writel(val, (valut + i*4));
au_writel(val, (hblut + i*4));
au_writel(val, (vblut + i*4));
au_writel(val, (hclut + i*4));
au_writel(val, (vclut + i*4));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -