📄 ddipu_sdc_overlay.cpp
字号:
//-----------------------------------------------------------------------------
// Copyright (C) 2004-2005, MOTOROLA, INC. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// MOTOROLA, INC.
//------------------------------------------------------------------------------
//
// Copyright (C) 2005-2007, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//
// File: ddipu_sdc_overlay.cpp
//
// Implementation of Overlay-related functions for DDIPU_SDC class, the
// DirectDraw display driver.
//
//-----------------------------------------------------------------------------
#include "precomp.h"
//-----------------------------------------------------------------------------
// External Functions
//-----------------------------------------------------------------------------
// External Variables
//-----------------------------------------------------------------------------
// Defines
#define LOCK_PP() EnterCriticalSection(&m_csPPLock)
#define UNLOCK_PP() LeaveCriticalSection(&m_csPPLock)
#if defined(PLAT_WPC) || defined(PLAT_SMARTPHONE)
#define IsOverlayMirrorUpDown(pd) (pd->dwFlags & DDOVER_MIRRORUPDOWN)
#else // PLAT_WPC || PLAT_SMARTPHONE
#define IsOverlayMirrorUpDown(pd) ((pd->dwFlags & DDOVER_DDFX) && (pd->overlayFX.dwDDFX & DDOVERFX_MIRRORUPDOWN))
#endif
#define DDOVER_KEY \
(DDOVER_KEYSRC | \
DDOVER_KEYSRCOVERRIDE |\
DDOVER_KEYDEST | \
DDOVER_KEYDESTOVERRIDE)
#define DUMP_OVERLAY_OP() {\
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->nBufPhysicalAddr 0x%08x\r\n"), m_pOverlaySurfaceOp->nBufPhysicalAddr)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->Width %d\r\n"), m_pOverlaySurfaceOp->Width)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->Height %d\r\n"), m_pOverlaySurfaceOp->Height)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->WidthHw %d\r\n"), m_pOverlaySurfaceOp->WidthHw)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->HeightHw %d\r\n"), m_pOverlaySurfaceOp->HeightHw)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->LineStride %d\r\n"), m_pOverlaySurfaceOp->LineStride)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->XOffset %d\r\n"), m_pOverlaySurfaceOp->XOffset)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->YOffset %d\r\n"), m_pOverlaySurfaceOp->YOffset)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->Transparency %d\r\n"), m_pOverlaySurfaceOp->Transparency)); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->isUpsideDown %s\r\n"), m_pOverlaySurfaceOp->isUpsideDown ? L"TRUE" : L"FALSE")); \
DEBUGMSG(1, (TEXT("Overlay OP: Overlay->ColorKeyMask 0x%08x\r\n"), m_pOverlaySurfaceOp->ColorKeyMask)); \
}
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
// Local Variables
//-----------------------------------------------------------------------------
// Local Functions
BOOL IsOverlaySurfEqual(pOverlaySurf_t pSurf1, pOverlaySurf_t pSurf2);
//------------------------------------------------------------------------------
//
// Function: UpdateOverlay
//
// This function repositions or modifies the visual
// attributes of an overlay surface.
//
// Parameters:
// pd
// [in, out] Pointer to a DDHAL_UPDATEOVERLAYDATA structure that
// contains the information required to update the overlay surface.
//
// Returns:
// Returns one of the following values:
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
//------------------------------------------------------------------------------
DWORD DDIPU_SDC::UpdateOverlay(LPDDHAL_UPDATEOVERLAYDATA pd)
{
/*
typedef struct _DDHAL_UPDATEOVERLAYDATA
{
LPDDRAWI_DIRECTDRAW_GBL lpDD; // driver struct
LPDDRAWI_DDRAWSURFACE_LCL lpDDDestSurface;// dest surface
RECTL rDest; // dest rect
LPDDRAWI_DDRAWSURFACE_LCL lpDDSrcSurface; // src surface
RECTL rSrc; // src rect
DWORD dwFlags; // flags
DDOVERLAYFX overlayFX; // overlay FX
HRESULT ddRVal; // return value
LPDDHALSURFCB_UPDATEOVERLAY UpdateOverlay; // PRIVATE: ptr to callback
} DDHAL_UPDATEOVERLAYDATA;
*/
overlaySurf_t overlaySurfInfo;
DDGPESurf* pSrcSurf = DDGPESurf::GetDDGPESurf(pd->lpDDSrcSurface);
if (pd->dwFlags & DDOVER_HIDE)
{
DEBUGMSG(GPE_ZONE_HW, (TEXT("DDIPU_SDC::OVERLAY HIDE REQUEST\r\n")));
if (pSrcSurf == m_pVisibleOverlay)
{
// If it was running, stop the post-processor
if (((m_iRotate != 0) || (pSrcSurf->PixelFormat() == ddgpePixelFormat_UYVY422) || (pSrcSurf->PixelFormat() == ddgpePixelFormat_YV12))
&& (m_PPConfiguration == PPConfiguration_Overlay))
{
// Do not stop PP until...
// 1) There are no messages in the PP operation queue
// 2) The PP Overlay thread is done working on the last operation
while(WaitForSingleObject(m_hReadPPOverlayQueue, 0) == WAIT_OBJECT_0)
{
// Sleep for a while since there are still operations in the queue
Sleep(10);
}
// If we are here, there are no operations left in the queue.
// Now, wait here if the PP is processing last operation.
EnterCriticalSection(&m_csOverlayShutdown);
LOCK_PP();
// In case we are in TV mode, let TV update thread know
// to restart PP
m_PPConfiguration = PPConfiguration_None;
PPStop(m_hPP);
UNLOCK_PP();
LeaveCriticalSection(&m_csOverlayShutdown);
}
// hide the overlay
//WaitForVSync();
DisableOverlay();
// reset visible overlay
m_pVisibleOverlay = NULL;
DEBUGMSG(GPE_ZONE_HW, (TEXT("DDIPU_SDC::OVERLAY HIDE!\r\n")));
}
else
{
// the overlay is not currently visible
// nothing we need to do here
}
pd->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
DDGPESurf* pDstSurf = DDGPESurf::GetDDGPESurf(pd->lpDDDestSurface);
if (pSrcSurf != m_pVisibleOverlay)
{
if (pd->dwFlags & DDOVER_SHOW)
{
DEBUGMSG(GPE_ZONE_HW, (TEXT("DDIPU_SDC::OVERLAY SHOW REQUEST\r\n")));
if (m_pVisibleOverlay != NULL)
{
// some other overlay is already visible
DEBUGMSG(GPE_ZONE_ERROR,
(TEXT("Error: Other overlay already visible!\r\n")));
pd->ddRVal = DDERR_OUTOFCAPS;
return DDHAL_DRIVER_HANDLED;
}
else
{
// we are going to make the overlay visible
// so mark it as such:
m_pVisibleOverlay = pSrcSurf;
DEBUGMSG(GPE_ZONE_HW, (TEXT("DDIPU_SDC::OVERLAY SHOW\r\n")));
}
}
else // DDOVER_SHOW not requested
{
// the overlay isn't visible, and we haven't been
// asked to make it visible, so nothing we need to do
pd->ddRVal = DD_OK;
return DDHAL_DRIVER_HANDLED;
}
}
overlaySurfInfo.Width = (UINT16)(pd->rDest.right - pd->rDest.left);
overlaySurfInfo.Height = (UINT16)(pd->rDest.bottom - pd->rDest.top);
switch(m_iRotate)
{
case DMDO_0:
case DMDO_180:
overlaySurfInfo.WidthHw = overlaySurfInfo.Width;
overlaySurfInfo.HeightHw = overlaySurfInfo.Height;
break;
case DMDO_90:
case DMDO_270:
// Rotation currently not supported...we need post-processing
// support to perform rotation
// DEBUGMSG(GPE_ZONE_ERROR,
// (TEXT("Error: Rotation unsupported...aborting\r\n")));
// pd->ddRVal = DDERR_UNSUPPORTED;
// return DDHAL_DRIVER_HANDLED;
overlaySurfInfo.WidthHw = overlaySurfInfo.Height;
overlaySurfInfo.HeightHw = overlaySurfInfo.Width;
break;
}
overlaySurfInfo.SrcRect.left = pd->rSrc.left;
overlaySurfInfo.SrcRect.top = pd->rSrc.top;
overlaySurfInfo.SrcRect.right = pd->rSrc.right;
overlaySurfInfo.SrcRect.bottom = pd->rSrc.bottom;
// Parameter validity check
if((pd->rDest.right > m_pMode->width) ||
(pd->rDest.bottom > m_pMode->height) ||
(overlaySurfInfo.WidthHw < DISP_MIN_WIDTH) ||
(m_iRotate && ((overlaySurfInfo.WidthHw & 0x7) || (overlaySurfInfo.HeightHw & 0x7))))
{
DEBUGMSG(GPE_ZONE_ERROR, (TEXT("%s: wrong parameters!\r\n"), __WFUNCTION__));
DUMP_OVERLAY_OP();
// We are aborting, so set the overlay to NULL
m_pVisibleOverlay = NULL;
pd->ddRVal = DDERR_INVALIDPARAMS;
return DDHAL_DRIVER_HANDLED;
}
overlaySurfInfo.Bpp = m_pMode->Bpp;
overlaySurfInfo.LineStride = overlaySurfInfo.WidthHw * m_pMode->Bpp / 8;
SetupOverlayPosition(&overlaySurfInfo, pd->rDest.left, pd->rDest.top);
// In TV mode, screen should remain unrotated.
if (m_bTVModeActive)
{
overlaySurfInfo.XOffset = (UINT16)pd->rDest.left;
overlaySurfInfo.YOffset = (UINT16)pd->rDest.top;
}
overlaySurfInfo.nBufPhysicalAddr = m_nLAWPhysical + pSrcSurf->OffsetInVideoMemory();
// Setup if overlay is flipped as upside-down
if(IsOverlayMirrorUpDown(pd))
{
DEBUGMSG(GPE_ZONE_HW, (TEXT("DDIPU_SDC UpdateOverlay: upside-down overlay is requested!\r\n")));
overlaySurfInfo.isUpsideDown = TRUE;
}
else
{
overlaySurfInfo.isUpsideDown = FALSE;
}
// Setup color key.
// IPU only supports one color key value and does not
// support a range. So, we take the low value
// from the color key mask to use as the color key.
// Initialize color key mask to 0xFFFFFFFF. If no color keying
// is specified, this 0xFFFFFFFF will indicate no color key.
overlaySurfInfo.ColorKeyMask = 0xFFFFFFFF;
// Default Graphics Window as Foreground.
// GW should only be Background in case of Destination Color Keying.
overlaySurfInfo.ColorKeyPlane = DisplayPlane_1;
if(pd->dwFlags & DDOVER_KEYSRC)
{
overlaySurfInfo.ColorKeyMask = pd->lpDDDestSurface->ddckCKSrcOverlay.dwColorSpaceLowValue;
overlaySurfInfo.ColorKeyPlane = DisplayPlane_1;
}
else if(pd->dwFlags & DDOVER_KEYSRCOVERRIDE)
{
overlaySurfInfo.ColorKeyMask = pd->overlayFX.dckSrcColorkey.dwColorSpaceLowValue;
overlaySurfInfo.ColorKeyPlane = DisplayPlane_1;
}
if(pd->dwFlags & DDOVER_KEYDEST)
{
overlaySurfInfo.ColorKeyMask = pd->lpDDDestSurface->ddckCKDestOverlay.dwColorSpaceLowValue;
overlaySurfInfo.ColorKeyPlane = DisplayPlane_0;
}
else if(pd->dwFlags & DDOVER_KEYDESTOVERRIDE)
{
overlaySurfInfo.ColorKeyMask = pd->overlayFX.dckDestColorkey.dwColorSpaceLowValue;
overlaySurfInfo.ColorKeyPlane = DisplayPlane_0;
// TODO: This is a hack required because of incompatibilities between DDraw
// and rotation. The wrong color key is provided in rotation mode if
// this is not included. For Windows Media Player, this should always
// be the color key: 0x841
if (m_iRotate)
{
//DEBUGMSG(1, (TEXT("DDIPU_SDC UpdateOverlay: Color Key hack - set to 0x841 for CE player overlay.\r\n")));
overlaySurfInfo.ColorKeyMask = 0x841;
}
}
// TODO: setup alpha blending
overlaySurfInfo.Transparency = 0;
// If overlay surface data has not changed, skip
// step to set up overlay and return.
if (!IsOverlaySurfEqual(m_pOverlaySurfaceOp, &overlaySurfInfo))
{
overlaySurfInfo.isOverlayWindowRunning = m_pOverlaySurfaceOp->isOverlayWindowRunning;
memcpy(m_pOverlaySurfaceOp, &overlaySurfInfo, sizeof(overlaySurf_t));
// Update the graphic window of the IPU display
pd->ddRVal = EnableOverlay(pSrcSurf);
}
else
{
pd->ddRVal = DD_OK;
}
return DDHAL_DRIVER_HANDLED;
}
//------------------------------------------------------------------------------
//
// Function: SetOverlayPosition
//
// This callback function changes the display coordinates of
// an overlay surface.
//
// Parameters:
// pd
// [in, out] Pointer to a DDHAL_SETOVERLAYPOSITIONDATA structure
// that contains the information required to change the display
// coordinates of an overlay surface.
//
// Returns:
// Returns one of the following values:
// DDHAL_DRIVER_HANDLED
// DDHAL_DRIVER_NOTHANDLED
//
//------------------------------------------------------------------------------
DWORD DDIPU_SDC::SetOverlayPosition(LPDDHAL_SETOVERLAYPOSITIONDATA pd)
{
/*
typedef struct _DDHAL_SETOVERLAYPOSITIONDATA
{
LPDDRAWI_DIRECTDRAW_GBL lpDD; // driver struct
LPDDRAWI_DDRAWSURFACE_LCL lpDDSrcSurface; // src surface
LPDDRAWI_DDRAWSURFACE_LCL lpDDDestSurface;// dest surface
LONG lXPos; // x position
LONG lYPos; // y position
HRESULT ddRVal; // return value
LPDDHALSURFCB_SETOVERLAYPOSITION SetOverlayPosition;
// PRIVATE: ptr to callback
} DDHAL_SETOVERLAYPOSITIONDATA;
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -