📄 ddipu_sdc_overlay.cpp
字号:
if(!m_pOverlaySurfaceOp->isOverlayWindowRunning)
{
// The overlay window is not running
pd->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
DDGPESurf* pSrcSurf = DDGPESurf::GetDDGPESurf(pd->lpDDSrcSurface);
if (pSrcSurf != m_pVisibleOverlay)
{
pd->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
// Parameter validity check
if(
(pd->lXPos + m_pOverlaySurfaceOp->Width > m_pMode->width) ||
(pd->lYPos + m_pOverlaySurfaceOp->Height > m_pMode->height)
)
{
DEBUGMSG(GPE_ZONE_ERROR, (TEXT("DDIPU_SDC SetOverlayPosition: error pd->lXPos [%d], pd->lYPos[%d]\r\n"), pd->lXPos, pd->lYPos));
pd->ddRVal = DDERR_INVALIDPARAMS;
return DDHAL_DRIVER_HANDLED;
}
SetupOverlayPosition(m_pOverlaySurfaceOp, pd->lXPos, pd->lYPos);
WaitForNotBusyOverlay();
// Go through full overlay window setup, in order to clip foreground
// if necessary (i.e., if FG exceeds BG in the X-direction).
OverlayWindowSetup();
pd->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
//------------------------------------------------------------------------------
//
// Function: SetVisibleSurfaceOverlay
//
// This function changes the overlay surface displayed by the IPU.
//
// Parameters:
// pSurf
// [in] Surface to be set as the visible overlay.
//
// pRcl
// [in] Rectangle within the surface to display.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
VOID DDIPU_SDC::SetVisibleSurfaceOverlay(DDGPESurf * pSurf, RECTL * pRcl)
{
PHYSICAL_ADDRESS physAddr;
DDIPU_SDCSurf *ppOutputSurf;
static UINT8 iCurrentBuf = 1;
ppOverlayOpData ppData;
UINT32 srcBufOffset, YBufLen;
// Bail out if the overlay window is not running
if (!m_pOverlaySurfaceOp->isOverlayWindowRunning)
{
return;
}
if ((m_iRotate != 0) || (pSurf->PixelFormat() == ddgpePixelFormat_UYVY422)
|| (pSurf->PixelFormat() == ddgpePixelFormat_YV12)) // Custom Format is YV12
{
// Alternate Post-processing output between two buffers
ppOutputSurf = (iCurrentBuf == 1) ? m_pPpOverlaySurface1 : m_pPpOverlaySurface2;
// Change current buffer for next iteration
iCurrentBuf = (iCurrentBuf == 1) ? 2 : 1;
if (pRcl == NULL)
{
srcBufOffset = 0;
}
else
{
// Compute buffer offset from source rectangle
srcBufOffset = pRcl->top * pSurf->Stride() + pRcl->left * pSurf->Bpp() / 8;
}
// Add input and output buffers to PP queues.
ppData.bufs.inputBuf = (UINT32 *)(m_nLAWPhysical + pSurf->OffsetInVideoMemory() + srcBufOffset);
ppData.bufs.outputBuf = (UINT32 *)(m_nLAWPhysical + ppOutputSurf->OffsetInVideoMemory());
if (m_ppData_Overlay.inputFormat == ppFormat_YUV420)
{
YBufLen = pSurf->Width() * pSurf->Height();
ppData.bufs.inputVBufOffset = YBufLen + (srcBufOffset / 4);
ppData.bufs.inputUBufOffset = YBufLen + (YBufLen/4) + (srcBufOffset / 4);
}
// If either
// a) TV mode is active but the overlay window is configured for LCD mode
// or
// b) LCD mode is active but the overlay window is configured for TV mode
// then we must reconfigure the overlay window.
// Note: This is a special case wherein we have switched in or out
// of TV mode while an overlay is active.
if (m_bTVModeActive ^ m_bOverlayConfiggedForTV)
{
// Disable overlay before reconfiguring
ForegroundWindowDisable();
// Set position and perform general configuration for SDC foreground window
OverlayWindowSetup();
// Re-enable overlay window
ForegroundWindowEnable();
// Handle special TV mode settings
if (!m_bTVModeActive)
{
// Normal settings
m_ppData_Overlay.outputSize.height = m_pOverlaySurfaceOp->HeightHw;
m_ppData_Overlay.outputSize.width = m_pOverlaySurfaceOp->WidthHw;
m_ppData_Overlay.outputStride = m_pOverlaySurfaceOp->LineStride;
}
else
{
// If we are in TV mode, do not rotate overlay
m_ppData_Overlay.flipRot.verticalFlip = FALSE;
m_ppData_Overlay.flipRot.horizontalFlip = FALSE;
m_ppData_Overlay.flipRot.rotate90 = FALSE;
// Upsize output dimensions for TV (640x480)
m_ppData_Overlay.outputSize.height = m_pOverlaySurfaceOp->Height * 2;
m_ppData_Overlay.outputSize.width = m_pOverlaySurfaceOp->Width * 2;
m_ppData_Overlay.outputStride = m_ppData_Overlay.outputSize.width * m_pMode->Bpp / 8;
}
m_bOverlayConfiggedForTV = m_bOverlayConfiggedForTV ? FALSE : TRUE;
// Ensure reconfiguration of PP with new config data
m_PPConfiguration = PPConfiguration_None;
}
ppData.configData = m_ppData_Overlay;
// Enqueue input buffer
if (!WriteMsgQueue(m_hWritePPOverlayQueue, &ppData, sizeof(ppOverlayOpData), 0, 0))
{
DEBUGMSG(GPE_ZONE_ERROR,
(TEXT("%s : Could not write to PP Overlay queue. Error!\r\n"), __WFUNCTION__));
}
}
else
{
// If no PP operation needed, just display surface
physAddr.QuadPart = m_nLAWPhysical + pSurf->OffsetInVideoMemory();
ForegroundWindowSetSrcBuffer(&physAddr);
// Enable Foreground...if it is already enabled,
// this call will just return.
ForegroundWindowEnable();
}
return;
}
//------------------------------------------------------------------------------
//
// Function: EnableOverlay
//
// This function enables the graphics window of the IPU.
//
// Parameters:
// None.
//
// Returns:
// DD_OK successful
// others failed
//
//------------------------------------------------------------------------------
HRESULT DDIPU_SDC::EnableOverlay(DDGPESurf *pOverlaySurf)
{
HRESULT result = DDERR_OUTOFCAPS;
if (m_pOverlaySurfaceOp->isOverlayWindowRunning)
{
WaitForNotBusyOverlay();
}
OverlayWindowSetup();
m_bOverlayConfiggedForTV = m_bTVModeActive ? TRUE : FALSE;
// If we will need PP, reset configuration status. Actual
// configuration will be done in PPOverlayRoutine().
if ((m_iRotate != 0) || (pOverlaySurf->PixelFormat() == ddgpePixelFormat_UYVY422)
|| (pOverlaySurf->PixelFormat() == ddgpePixelFormat_YV12)) // Custom Format is YV12
{
LOCK_PP();
// Stop whomever is already running the PP,
// so that it can be reconfigured and run for TV.
PPStop(m_hPP);
// Configure PP task
SetPPConfigForOverlay(pOverlaySurf);
PPConfigure(m_hPP, &m_ppData_Overlay);
m_PPConfiguration = PPConfiguration_Overlay;
// Start PP task
// Note: The post-processor will not acutally
// process frames until the buffers are added.
// This occures within SetVisibleSurfaceOverlay
PPStart(m_hPP);
UNLOCK_PP();
}
// Only enable if we are not already running
if (!m_pOverlaySurfaceOp->isOverlayWindowRunning)
{
m_pOverlaySurfaceOp->isOverlayWindowRunning = TRUE;
}
SetVisibleSurfaceOverlay(pOverlaySurf, (RECTL *)&m_pOverlaySurfaceOp->SrcRect);
result = DD_OK;
#if defined(PLAT_WPC) || defined(PLAT_SMARTPHONE)
DEBUGMSG(GPE_ZONE_INIT, (TEXT("DDIPU_SDC EnableOverlay: result 0x%08x\r\n"), result));
#else
DEBUGMSG(HAL_ZONE_INIT, (TEXT("DDIPU_SDC EnableOverlay: result 0x%08x\r\n"), result));
#endif
return result;
}
//------------------------------------------------------------------------------
//
// Function: DisableOverlay
//
// This function disables the graphics window of the IPU.
//
// Parameters:
// None.
//
// Returns:
// DD_OK successful
// DDERR_EXCEPTION failed (for WinCE/PMC)
// DDERR_GENERIC failed (for Windows Mobile/PocketPC)
//
//------------------------------------------------------------------------------
HRESULT DDIPU_SDC::DisableOverlay(VOID)
{
if (m_pOverlaySurfaceOp->isOverlayWindowRunning)
{
if (!ForegroundWindowDisable())
{
#if defined(PLAT_WPC) || defined(PLAT_SMARTPHONE)
return DDERR_GENERIC;
#else
return DDERR_EXCEPTION;
#endif
}
memset(m_pOverlaySurfaceOp, 0x00, sizeof(overlaySurf_t));
}
return DD_OK;
}
//------------------------------------------------------------------------------
//
// Function: PPOverlayThread
//
// This method is a thread executed whenever we enter TV mode.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void DDIPU_SDC::PPOverlayThread(LPVOID lpParameter)
{
DDIPU_SDC *pDDIPU_SDC = (DDIPU_SDC *)lpParameter;
pDDIPU_SDC->PPOverlayRoutine();
return;
}
//------------------------------------------------------------------------------
//
// Function: PPOverlayRoutine
//
// This routine is activated whenever the UI needs to be
// updated. It then waits on the SDC BG EOF interrupt, and
// calls to perform upsizing and set the upsized UI as the
// next SDC BG buffer.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void DDIPU_SDC::PPOverlayRoutine(void)
{
PHYSICAL_ADDRESS physAddr;
ppOverlayOpData ppData;
DWORD dwFlags, bytesRead;
CeSetThreadPriority(GetCurrentThread(), 100);
while (1)
{
WaitForSingleObject(m_hReadPPOverlayQueue, INFINITE);
// This object helps us synchronize with the call to
// turn off overlays
EnterCriticalSection(&m_csOverlayShutdown);
// Now, read input buffer queue to retrieve buffer pointer.
if (!ReadMsgQueue(m_hReadPPOverlayQueue, &ppData, sizeof(ppOverlayOpData), &bytesRead, 0, &dwFlags))
{
DEBUGMSG (GPE_ZONE_ERROR, (TEXT("%s: Error: No input buffer to read from input queue\r\n"), __WFUNCTION__));
}
// Do not perform PP actions if we have moved out
// of D0 (power on) state. Otherwise, IPU clocks
// may be disabled, which will lead to PP hang.
if (m_Dx != D0)
{
LeaveCriticalSection(&m_csOverlayShutdown);
continue;
}
LOCK_PP();
m_iLastOverlayUpdateTime = GetTickCount();
// See if we need to re-configure PP
if (m_PPConfiguration != PPConfiguration_Overlay)
{
// Stop whomever is already running the PP,
// so that it can be reconfigured and run for TV.
PPStop(m_hPP);
// We can run PPConfigure here because EnableOverlay
// should have already been called to set up m_ppData_Overlay
PPConfigure(m_hPP, &ppData.configData);
m_PPConfiguration = PPConfiguration_Overlay;
// Start PP task
// Note: The post-processor will not acutally
// process frames until the buffers are added.
// This occures within SetVisibleSurfaceOverlay
PPStart(m_hPP);
}
PPAddBuffers(m_hPP, &ppData.bufs);
// Wait for End of Frame
WaitForSingleObject(m_hPPEOFEvent, 1000);
UNLOCK_PP();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -