⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddipu_sdc_overlay.cpp

📁 IMX31开发板
💻 CPP
📖 第 1 页 / 共 3 页
字号:

    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 + -