📄 dispfmt.c
字号:
if( dispfmt_ApplyFlip() != PASS )
{
rearProjection = temp;
return FAIL;
}
if( dispfmt_ApplyDisplay() != PASS )
{
rearProjection = temp;
dispfmt_ApplyFlip();
return FAIL;
}
return PASS;
}
/****************************************************************************/
/* Ceiling projection user controls */
/****************************************************************************/
int08 dispfmt_SetCeilingProjection( uint08 enable )
{
int16 min, max;
uint08 temp1;
int16 temp2;
temp1 = ceilingMount;
temp2 = anglePitch;
/* Pitch range for Angle Keystone flips when using Ceiling Mount. Ensure that it is within bounds */
if( enable != ceilingMount )
{
/* get the range, then negate it -- note that the parameters to DISP_GetKeystonePitchRange are reversed */
DISP_GetKeystonePitchRange( &min, &max );
min *= -1;
max *= -1;
/* limit the keystone value to the new range */
if( anglePitch > max )
anglePitch = max;
if( anglePitch < min )
anglePitch = min;
}
ceilingMount = enable;
if( dispfmt_ApplyFlip() != PASS )
{
ceilingMount = temp1;
anglePitch = temp2;
return FAIL;
}
/* reapply keystone because the vertical offset needs to be negated (and pitch might have changed) */
if( dispfmt_ApplyKeystone() != PASS )
{
ceilingMount = temp1;
anglePitch = temp2;
dispfmt_ApplyFlip();
return FAIL;
}
/* must call applyDisplay to apply new values to hardware */
if( dispfmt_ApplyDisplay() != PASS )
{
ceilingMount = temp1;
anglePitch = temp2;
dispfmt_ApplyFlip();
dispfmt_ApplyKeystone();
return FAIL;
}
return PASS;
}
/****************************************************************************/
/* Keystone user controls */
/****************************************************************************/
int08 dispfmt_GetKeystoneAnglePitchLimits( int16 *min, int16 *max )
{
/* note: this requires DISP_SetKeystoneAngles to be called prior to this function */
return DISP_GetKeystonePitchRange( max, min );
}
int08 dispfmt_GetKeystoneAnglePitch( int16 *pitch )
{
*pitch = anglePitch;
return TRUE;
}
void dispfmt_SetKeystoneConfigOverride( uint16 throwratio, int16 offset )
{
throwRatio = throwratio;
verticalOffset = offset;
}
int08 dispfmt_SetKeystoneAnglePitch( int16 pitch )
{
int16 min, max, temp;
dispfmt_GetKeystoneAnglePitchLimits( &min, &max );
if( pitch < min || pitch > max )
return FAIL;
temp = anglePitch;
anglePitch = pitch;
if( dispfmt_ApplyKeystone() != PASS )
{
anglePitch = temp;
return FAIL;
}
if( dispfmt_ApplyDisplay() != PASS )
{
anglePitch = temp;
dispfmt_ApplyKeystone();
return FAIL;
}
return PASS;
}
/****************************************************************************/
/* Configure the deinterlacer */
/****************************************************************************/
void dispfmt_ApplyDEI( void )
{
DP_SOURCEDESC *srcDesc;
datapath_GetSourceDesc( &srcDesc );
if( !srcDesc->sourceActive )
{
return;
}
if( srcDesc->okToDeinterlace )
{
DEI_SetMotionAdaptiveMode(DEI_MOTION_ADAPTIVE);
DEI_SetIntraFieldInterpolationStrength(DEI_OPTIMIZED_3);
DEI_Enable( TRUE );
/* configure film mode cadence detection */
if( 57.0f <= srcDesc->inputFrameRate && srcDesc->inputFrameRate <= 63.0f ) /* search for 3:2 cadence on 60Hz sources */
{
DEI_SetFilmModeLockThresholds( 1, 1 );
DEI_SetFilmMode( DEI_MODE_SW_3_2 );
dbmsg_trace( DBM_DPATH, "DEI Enabled (NTSC)\r\n" );
}
else if( 47.0f <= srcDesc->inputFrameRate && srcDesc->inputFrameRate <= 53.0f ) /* search for 2:2 cadence on 50Hz sources */
{
DEI_SetFilmModeLockThresholds( 10, 1 );
DEI_SetFilmMode( DEI_MODE_SW_2_2 );
dbmsg_trace( DBM_DPATH, "DEI Enabled (PAL)\r\n" );
}
else
{
DEI_SetFilmMode( DEI_MODE_DISABLE );
dbmsg_trace( DBM_DPATH, "DEI Enabled (unknown standard)\r\n" );
}
}
else
{
DEI_Enable( FALSE );
dbmsg_trace( DBM_DPATH, "DEI Disabled\r\n" );
}
}
void dispfmt_CalculateCroppedArea( DP_SOURCEDESC *srcDesc, DISP_DISPLAY_CONFIG *disp_cfg )
{
disp_cfg->CroppedArea.FirstPixel = 0;
disp_cfg->CroppedArea.FirstLine = 0;
disp_cfg->CroppedArea.PixelsPerLine = srcDesc->inputWidth;
disp_cfg->CroppedArea.LinesPerFrame = srcDesc->inputHeight;
/* crop splash if the DisplayArea is smaller than the splash */
/* overscan, magnify, and pan & scan are not supported */
if( srcDesc->activeDisplay == DP_SPLASH )
{
if( disp_cfg->CroppedArea.PixelsPerLine > disp_cfg->DisplayArea.PixelsPerLine )
{
disp_cfg->CroppedArea.FirstPixel = (disp_cfg->CroppedArea.PixelsPerLine - disp_cfg->DisplayArea.PixelsPerLine)/2;
disp_cfg->CroppedArea.PixelsPerLine = disp_cfg->DisplayArea.PixelsPerLine;
}
if( disp_cfg->CroppedArea.LinesPerFrame > disp_cfg->DisplayArea.LinesPerFrame )
{
disp_cfg->CroppedArea.FirstLine = (disp_cfg->CroppedArea.LinesPerFrame - disp_cfg->DisplayArea.LinesPerFrame)/2;
disp_cfg->CroppedArea.LinesPerFrame = disp_cfg->DisplayArea.LinesPerFrame;
}
return;
}
/* overscan, magnify, and pan & scan are not supported for TPG or SFG */
if( srcDesc->activeDisplay != DP_EXTERNAL )
return;
/* calculate CroppedArea for external sources */
/* compute cropping for overscan */
if( overscan == TRUE )
{
disp_cfg->CroppedArea.PixelsPerLine -= srcDesc->inputWidth/10;
disp_cfg->CroppedArea.LinesPerFrame -= srcDesc->inputHeight/10;
}
/* compute magnification -- scale_factor = (magnify_percent + 100%)/100 */
disp_cfg->CroppedArea.PixelsPerLine = disp_cfg->CroppedArea.PixelsPerLine * 100 / (magnifyPercent + 100);
disp_cfg->CroppedArea.LinesPerFrame = disp_cfg->CroppedArea.LinesPerFrame * 100 / (magnifyPercent + 100);
/* compute pan */
disp_cfg->CroppedArea.FirstPixel += (srcDesc->inputWidth - disp_cfg->CroppedArea.PixelsPerLine)/2; /* center image */
minPan = -1 * disp_cfg->CroppedArea.FirstPixel;
maxPan = srcDesc->inputWidth - (disp_cfg->CroppedArea.FirstPixel + disp_cfg->CroppedArea.PixelsPerLine);
if( pan < minPan )
{
disp_cfg->CroppedArea.FirstPixel += minPan;
}
else if( pan > maxPan )
{
disp_cfg->CroppedArea.FirstPixel += maxPan;
}
else
{
disp_cfg->CroppedArea.FirstPixel += pan;
}
/* compute scan */
disp_cfg->CroppedArea.FirstLine += (srcDesc->inputHeight - disp_cfg->CroppedArea.LinesPerFrame)/2; /* center image */
minScan = -1 * disp_cfg->CroppedArea.FirstLine;
maxScan = srcDesc->inputHeight - (disp_cfg->CroppedArea.FirstLine + disp_cfg->CroppedArea.LinesPerFrame);
if( scan < minScan )
{
disp_cfg->CroppedArea.FirstLine += minScan;
}
else if( scan > maxScan )
{
disp_cfg->CroppedArea.FirstLine += maxScan;
}
else
{
disp_cfg->CroppedArea.FirstLine += scan;
}
}
void dispfmt_CalculateDisplayArea( DP_SOURCEDESC *srcDesc, DISP_DISPLAY_CONFIG *disp_cfg )
{
uint16 dmdWidth, dmdHeight;
uint16 ratiox, ratioy;
DMD_GetResolution( &dmdWidth, &dmdHeight );
/* set the aspect ratio correction */
switch( aspectRatio )
{
case 1: //native
ratiox = srcDesc->nativeWidth;
ratioy = srcDesc->nativeHeight;
break;
case 2: //4:3
ratiox = 4;
ratioy = 3;
break;
case 3: //16:9
ratiox = 16;
ratioy = 9;
break;
case 0: //fill (uses DMD aspect ratio)
default:
ratiox = dmdWidth;
ratioy = dmdHeight;
break;
}
/* calculate the output image size (number of lines) */
switch( imageSize )
{
case 2: //Manual
if( imageSizeSteps > dmdHeight )
{
disp_cfg->DisplayArea.LinesPerFrame = dmdHeight;
}
else
{
disp_cfg->DisplayArea.LinesPerFrame = imageSizeSteps;
}
break;
case 1: //Native
if( srcDesc->nativeHeight <= dmdHeight )
{
disp_cfg->DisplayArea.LinesPerFrame = srcDesc->nativeHeight;
}
else
{
disp_cfg->DisplayArea.LinesPerFrame = dmdHeight;
}
break;
case 0: //Fill
default:
disp_cfg->DisplayArea.LinesPerFrame = dmdHeight;
break;
}
/* calculate the image width based on the image size and aspect ratio */
disp_cfg->DisplayArea.PixelsPerLine = disp_cfg->DisplayArea.LinesPerFrame * ratiox / ratioy;
/* limit to the size of the DMD */
if( disp_cfg->DisplayArea.PixelsPerLine > dmdWidth )
{
disp_cfg->DisplayArea.PixelsPerLine = dmdWidth;
disp_cfg->DisplayArea.LinesPerFrame = disp_cfg->DisplayArea.PixelsPerLine * ratioy / ratiox;
}
/* calculate the image position */
disp_cfg->Centered = FALSE;
/* calculate the horizontal position -- image must be centered to work correctly with keystone */
disp_cfg->DisplayArea.FirstPixel = (dmdWidth - disp_cfg->DisplayArea.PixelsPerLine)/2; /* center image */
/* calculate the vertical position */
disp_cfg->DisplayArea.FirstLine = (dmdHeight - disp_cfg->DisplayArea.LinesPerFrame)/2; /* center image */
minImagePosy = -1 * disp_cfg->DisplayArea.FirstLine;
maxImagePosy = dmdHeight - (disp_cfg->DisplayArea.FirstLine + disp_cfg->DisplayArea.LinesPerFrame);
if( imagePosy < minImagePosy )
{
disp_cfg->DisplayArea.FirstLine += minImagePosy;
}
else if( imagePosy > maxImagePosy )
{
disp_cfg->DisplayArea.FirstLine += maxImagePosy;
}
else
{
disp_cfg->DisplayArea.FirstLine += imagePosy;
}
}
void dispfmt_ApplyScalingFilter( DP_SOURCEDESC *srcDesc, DISP_DISPLAY_CONFIG *disp_cfg )
{
if( srcDesc->isVideo || anglePitch != 0.0f )
{
if( disp_cfg->CroppedArea.LinesPerFrame >= disp_cfg->DisplayArea.LinesPerFrame )
DISP_SetScalingFilter( DISP_VIDEO_DOWNSCALING );
else
DISP_SetScalingFilter( DISP_VIDEO_UPSCALING );
}
else
{
if( disp_cfg->CroppedArea.LinesPerFrame >= disp_cfg->DisplayArea.LinesPerFrame )
DISP_SetScalingFilter( DISP_GRAPHICS_DOWNSCALING );
else
DISP_SetScalingFilter( DISP_GRAPHICS_UPSCALING );
}
}
int08 dispfmt_ApplyDisplay( void )
{
DISP_DISPLAY_CONFIG disp_cfg;
int08 result = PASS;
DP_SOURCEDESC *srcDesc;
datapath_GetSourceDesc( &srcDesc );
disp_cfg.Centered = FALSE;
dispfmt_CalculateDisplayArea( srcDesc, &disp_cfg );
dispfmt_CalculateCroppedArea( srcDesc, &disp_cfg );
/* apply the settings to hardware */
result = DISP_SetDisplay( SRC_PRIMARY, disp_cfg );
if( result < PASS )
{
dbmsg_ftrace( DBM_DPATH, "dispfmt: DISP_SetDisplay failed (ret=%d)\r\n", result );
dbmsg_ftrace( DBM_DPATH, " CroppedArea = { %d, %d, %d, %d }\r\n", disp_cfg.CroppedArea.FirstPixel, disp_cfg.CroppedArea.FirstLine, disp_cfg.CroppedArea.PixelsPerLine, disp_cfg.CroppedArea.LinesPerFrame );
dbmsg_ftrace( DBM_DPATH, " DisplayArea = { %d, %d, %d, %d }\r\n", disp_cfg.DisplayArea.FirstPixel, disp_cfg.DisplayArea.FirstLine, disp_cfg.DisplayArea.PixelsPerLine, disp_cfg.DisplayArea.LinesPerFrame );
return FAIL;
}
dispfmt_ApplyScalingFilter( srcDesc, &disp_cfg );
/* signal the GUI to reposition itself as the active area may have changed */
guiStyle_Redraw();
return PASS;
}
int08 dispfmt_ApplyFlip( void )
{
/* these equations assume a horizontal (East/West) flip by the optics */
DISP_SetHorizontalFlip( (!rearProjection) ^ ceilingMount );
DISP_SetVerticalFlip( ceilingMount );
return PASS;
}
int08 dispfmt_ApplyKeystone( void )
{
int16 offset;
int08 result;
offset = verticalOffset;
/* if projector is upside-down, we must negate the vertical offset */
if( ceilingMount )
offset *= -1;
result = DISP_SetKeystoneAngles( anglePitch, throwRatio, offset );
if( result != PASS )
{
dbmsg_ftrace( DBM_DPATH, "dispfmt: DISP_SetKeystoneAngles failed (ret=%d)\r\n", result );
dbmsg_ftrace( DBM_DPATH, " angle=%4x TR=%x off=%x\r\n", anglePitch, throwRatio, offset );
return FAIL;
}
return PASS;
}
void dispfmt_RestoreDefaults()
{
DP_SOURCEDESC *srcDesc;
datapath_GetSourceDesc( &srcDesc );
/* set all EEPROM values to defaults from flash */
EE_PUTVAR( UserMachine.Projector.AspectRatio, gpSettings->UserMachine.Projector.AspectRatio );
EE_PUTVAR( UserMachine.Projector.ImageSizeEnum, gpSettings->UserMachine.Projector.ImageSizeEnum );
EE_PUTVAR( UserMachine.Projector.ImageSizeManualSteps, gpSettings->UserMachine.Projector.ImageSizeManualSteps );
EE_PUTVAR( UserMachine.Projector.ImageOffset, gpSettings->UserMachine.Projector.ImageOffset );
if( srcDesc->isVideo == TRUE && srcDesc->activeDisplay == DP_EXTERNAL )
{
EE_PUTVAR( UserMachine.ConnectorSettings[srcDesc->connector].Overscan, gpSettings->UserMachine.ConnectorSettings[srcDesc->connector].Overscan );
}
EE_PUTVAR( UserMachine.Projector.KeystonePitch, gpSettings->UserMachine.Projector.KeystonePitch );
EE_PUTVAR( UserMachine.Projector.AutoKeystone, gpSettings->UserMachine.Projector.AutoKeystone );
/* apply settings to projector */
dispfmt_ConfigureForSource( TRUE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -