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

📄 ddipu_sdc_tv.cpp

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 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-2006, 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_tv.cpp
//
//  Implementation of DDIPU_SDC TV mode-related functions.
//
//------------------------------------------------------------------------------
#include "precomp.h"


//------------------------------------------------------------------------------
// External Functions


//------------------------------------------------------------------------------
// External Variables


//------------------------------------------------------------------------------
// Defines

#define RETAIL_MSGS 0

#define LOCK_PP()      EnterCriticalSection(&m_csPPLock)
#define UNLOCK_PP()    LeaveCriticalSection(&m_csPPLock)

//------------------------------------------------------------------------------
// Types


//------------------------------------------------------------------------------
// Global Variables


//------------------------------------------------------------------------------
// Local Variables


//------------------------------------------------------------------------------
// Local Functions


//------------------------------------------------------------------------------
//
// Function: TVUpdateThread
//
// This method is a thread executed whenever we enter TV mode.
//
// Parameters:
//      None.
//
// Returns:
//      None.
//
//------------------------------------------------------------------------------
void DDIPU_SDC::TVUpdateThread(LPVOID lpParameter)
{
    DDIPU_SDC *pDDIPU_SDC = (DDIPU_SDC *)lpParameter;

    pDDIPU_SDC->TVUpdateRoutine();

    return;
}


//------------------------------------------------------------------------------
//
// Function: TVUpdateRoutine
//
// 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::TVUpdateRoutine(void)
{
    while (1)
    {
        UINT32 time, iOverlayInterval;

        // Wait for request to update the surface
        WaitForSingleObject(m_hTVUpdateRequest, INFINITE);

        EnterCriticalSection(&m_csDrawLock);

        // Check to make sure we are still in TV mode and
        // thus requiring the TV update.
        if (!m_bTVModeActive)
        {
            LeaveCriticalSection(&m_csDrawLock);
            continue;
        }

        time = GetTickCount();
        //DEBUGMSG(1, (TEXT("%s: TV Update request received at time %d:%d\r\n"), __WFUNCTION__, time/60, time%60));

        // Wait for background plane to complete current refresh.
        DisplayPlaneWaitForNotBusy(DisplayPlane_0);

        // We have received SDC BG EOF interrupt, so
        // now we upscale and update the buffer.
        TVUpdateBuffer();

        LeaveCriticalSection(&m_csDrawLock);

		// We would like to put the UI update to sleep
		// when we know that video playback or other heavy
		// use of overlays is occurring.  However, relying
		// on whether the overlay is currently being shown
		// is not sufficient.  We would ideally be able to
		// flag when video is being played, and change our
		// Sleep time here based on whether overlays are in
		// heavy use or not.

		iOverlayInterval = GetTickCount() - m_iLastOverlayUpdateTime;

        //DEBUGMSG(1, (TEXT("%s: Interval since last overlay update: %d\r\n"), __WFUNCTION__, iOverlayInterval));
		if (iOverlayInterval > 500)
		{
	        // Now sleep for 33ms, so that we only update at a
	        // maximum of a 30FPS rate.  1000/30 = 33.3
	        Sleep(20);
		}
		else
		{
	        Sleep(100);
		}
    }
}


//------------------------------------------------------------------------------
//
// Function: TVUpdateBuffer
//
// This method upsizes the current primary buffer and puts the result
// in a TV out buffer.
//
// Parameters:
//      None.
//
// Returns:
//      S_OK            successful
//      others          failed
//
//------------------------------------------------------------------------------
void DDIPU_SDC::TVUpdateBuffer(void)
{
    DDIPU_SDCSurf *ppOutputSurf;
    ppBuffers bufs;
    static int lastRotation = DMDO_0;

    UINT32 iDirtyRegions;
    LPRECT pRectangles;
    UINT32 i;
    UINT32 srcBufOffset, dstBufOffset;

    static BOOL singleRegionConfig = FALSE;

    UINT32 time;
    time = GetTickCount();
    RETAILMSG(RETAIL_MSGS, (TEXT("%s: Waiting for PP Lock for TV %d:%d\r\n"), __WFUNCTION__, time/60, time%60));

    LOCK_PP();

    RETAILMSG(RETAIL_MSGS, (TEXT("%s: Locking PP for TV %d:%d\r\n"), __WFUNCTION__, time/60, time%60));

    // Determine source and target rectangle by reading
    // dirty rectangle regions
    EnterCriticalSection(&m_csDirtyRect);

    iDirtyRegions = m_pDirtyRect->GetNumDirtyRegions();
    pRectangles = (LPRECT) LocalAlloc(LPTR, sizeof(RECT) * iDirtyRegions);
    m_pDirtyRect->GetDirtyRegions(pRectangles, iDirtyRegions);

    // Reset event to re-synchronize updates to primary surface
    // with calls to update the TV.
    ResetEvent(m_hTVUpdateRequest);

    LeaveCriticalSection(&m_csDirtyRect);

    // TODO: Update based on dirty rectangles....
    if ((iDirtyRegions == 0) || (iDirtyRegions == m_iNumDirtyRegions))
    {
        // If no dirty regions, just update the entire UI.

        if (singleRegionConfig || (m_PPConfiguration != PPConfiguration_TV))
        {
            // Stop whomever is already running the PP,
            // so that it can be reconfigured and run for TV.
            PPStop(m_hPP);

            RECT fullUI = {0, 0, 319, 239};

            SetPPConfigForTV(fullUI);
            m_PPConfiguration = PPConfiguration_TV;
            PPConfigure(m_hPP, &m_ppData_TV);

            RETAILMSG(RETAIL_MSGS, (TEXT("%s: Configged for TV\r\n"), __WFUNCTION__));

            // Start PP task
            // Note: The post-processor will not acutally
            // process frames until the buffers are added.
            // This occurs within SetVisibleSurfaceOverlay
            PPStart(m_hPP);

            singleRegionConfig = FALSE;
        }

        // Set Post-processing output to TV buffer
        ppOutputSurf = m_pTVBuffer1;

        RETAILMSG(0, (TEXT("%s: m_nLAWPhysical = %x \nm_pPrimarySurface->OffsetInVideoMemory() = %x\r\n"),
            __WFUNCTION__, m_nLAWPhysical, m_pPrimarySurface->OffsetInVideoMemory()));

        // Add input and output buffers to PP queues.
        bufs.inputBuf = (UINT32 *)(m_nLAWPhysical + m_pPrimarySurface->OffsetInVideoMemory());
        bufs.outputBuf = (UINT32 *)(m_nLAWPhysical + ppOutputSurf->OffsetInVideoMemory());
        PPAddBuffers(m_hPP, &bufs);

        // Wait for End of Frame
        WaitForSingleObject(m_hPPEOFEvent, INFINITE);

    }
    else
    {
        // Currently, we update the entire primary surface.
        for (i = 0; i < iDirtyRegions; i++)
        {
            // Only stop, configure, and start if one of the following
            // cases is true:
            //      1) Current configuration is for Overlay
            //      2) Current configuration
            if (!(singleRegionConfig && (m_PPConfiguration == PPConfiguration_TV)))
            {
                // Stop whomever is already running the PP,
                // so that it can be reconfigured and run for TV.
                PPStop(m_hPP);

                SetPPConfigForTV(pRectangles[i]);
                m_PPConfiguration = PPConfiguration_TV;
                PPConfigure(m_hPP, &m_ppData_TV);

                RETAILMSG(RETAIL_MSGS, (TEXT("%s: Configged for TV\r\n"), __WFUNCTION__));

                // Start PP task
                // Note: The post-processor will not actually
                // process frames until the buffers are added.
                // This occurs within SetVisibleSurfaceOverlay
                PPStart(m_hPP);

                singleRegionConfig = TRUE;
            }

            // Set Post-processing output to TV buffer
            ppOutputSurf = m_pTVBuffer1;

            RETAILMSG(0, (TEXT("%s: m_nLAWPhysical = %x \nm_pPrimarySurface->OffsetInVideoMemory() = %x\r\n"),
                __WFUNCTION__, m_nLAWPhysical, m_pPrimarySurface->OffsetInVideoMemory()));

            // Compute buffer offset from source rectangle
            switch (m_iRotate)
            {
                case DMDO_0:
                case DMDO_180:
                    srcBufOffset = (pRectangles[i].top * m_nScreenWidth + pRectangles[i].left) * m_pMode->Bpp / 8;
                    dstBufOffset = ((pRectangles[i].top * 2) * (m_nScreenWidth * 2) + pRectangles[i].left * 2) * m_pMode->Bpp / 8;
                    break;
                case DMDO_90:
                case DMDO_270:
                    srcBufOffset = (pRectangles[i].left * m_nScreenHeight + (m_nScreenHeight - pRectangles[i].bottom)) * m_pMode->Bpp / 8;
                    dstBufOffset = ((pRectangles[i].top * 2) * (m_nScreenWidth * 2) + pRectangles[i].left * 2) * m_pMode->Bpp / 8;
                    break;
            }


            // Add input and output buffers to PP queues.
            bufs.inputBuf = (UINT32 *)(m_nLAWPhysical + m_pPrimarySurface->OffsetInVideoMemory() + srcBufOffset);
            bufs.outputBuf = (UINT32 *)(m_nLAWPhysical + ppOutputSurf->OffsetInVideoMemory() + dstBufOffset);
            PPAddBuffers(m_hPP, &bufs);

            // Wait for End of Frame
            WaitForSingleObject(m_hPPEOFEvent, INFINITE);
        }
    }

    //RETAILMSG(1, (TEXT("%s: Finished TV UI processing, regions = %d, time = %d\r\n"), __WFUNCTION__, iDirtyRegions, GetTickCount() - time));

    RETAILMSG(RETAIL_MSGS, (TEXT("%s: Unlocking PP for TV %d:%d\r\n"), __WFUNCTION__, time/60, time%60));
    UNLOCK_PP();

    LocalFree(pRectangles);

    return;
}


//------------------------------------------------------------------------------
//
// Function: ConfigPPForTV
//
// This function configure the Post-processor to perform rotation,
// color space conversion, and resizing for the video overlay.
//
// Parameters:
//      pOverlaySurf
//          [in] Overlay surface.
//
// Returns:
//      None.
//
//------------------------------------------------------------------------------
void DDIPU_SDC::SetPPConfigForTV(RECT srcRect)
{
    UINT16 rectWidth, rectHeight;
    int srcSurfWidth;

    // Set up post-processing configuration data

    //RETAILMSG(1, (TEXT("%s: Configuring for TV\r\n"), __WFUNCTION__));

    // Set up input format and data width
    m_ppData_TV.inputFormat = ppFormat_RGB;
    m_ppData_TV.inputDataWidth = ppDataWidth_16BPP;
    m_ppData_TV.inputRGBPixelFormat.component0_offset = 0;
    m_ppData_TV.inputRGBPixelFormat.component1_offset = 5;
    m_ppData_TV.inputRGBPixelFormat.component2_offset = 11;
    m_ppData_TV.inputRGBPixelFormat.component0_width = 5;
    m_ppData_TV.inputRGBPixelFormat.component1_width = 6;
    m_ppData_TV.inputRGBPixelFormat.component2_width = 5;

    // Set up output format and data width
    m_ppData_TV.outputFormat = ppFormat_RGB;
    m_ppData_TV.outputDataWidth = ppDataWidth_16BPP;
    m_ppData_TV.outputRGBPixelFormat.component0_offset = 0;
    m_ppData_TV.outputRGBPixelFormat.component1_offset = 5;
    m_ppData_TV.outputRGBPixelFormat.component2_offset = 11;
    m_ppData_TV.outputRGBPixelFormat.component0_width = 5;
    m_ppData_TV.outputRGBPixelFormat.component1_width = 6;
    m_ppData_TV.outputRGBPixelFormat.component2_width = 5;

    // Set up post-processing channel CSC parameters
    m_ppData_TV.CSCEquation = ppCSCNoOp;

    rectWidth = (UINT16) (srcRect.right - srcRect.left + 1);
    rectHeight = (UINT16) (srcRect.bottom - srcRect.top + 1);

    switch (m_iRotate)
    {
        case DMDO_0:
        case DMDO_180:
            m_ppData_TV.inputSize.height = rectHeight;
            m_ppData_TV.inputSize.width = rectWidth;
            srcSurfWidth = m_pMode->width;
            break;
        case DMDO_270:
        case DMDO_90:
            m_ppData_TV.inputSize.height = rectWidth;
            m_ppData_TV.inputSize.width = rectHeight;
            srcSurfWidth = m_pMode->height;
            break;
    }
    m_ppData_TV.inputStride = srcSurfWidth * (m_pMode->Bpp / 8);

    // If our screen orientation is rotated, we want to undo that
    // rotation for TV out.  TV out should never be rotated.
    switch (m_iRotate)
    {
        case DMDO_0:
            m_ppData_TV.flipRot.verticalFlip = FALSE;
            m_ppData_TV.flipRot.horizontalFlip = FALSE;
            m_ppData_TV.flipRot.rotate90 = FALSE;
            break;
        case DMDO_90:
            // Rotate another 270
            m_ppData_TV.flipRot.verticalFlip = FALSE;
            m_ppData_TV.flipRot.horizontalFlip = FALSE;
            m_ppData_TV.flipRot.rotate90 = TRUE;
            break;
        case DMDO_180:
            // Rotate 180
            m_ppData_TV.flipRot.verticalFlip = TRUE;
            m_ppData_TV.flipRot.horizontalFlip = TRUE;
            m_ppData_TV.flipRot.rotate90 = FALSE;
            break;
        case DMDO_270:
            // Rotate 90
            m_ppData_TV.flipRot.verticalFlip = TRUE;
            m_ppData_TV.flipRot.horizontalFlip = TRUE;
            m_ppData_TV.flipRot.rotate90 = TRUE;
            break;
    }

    // TV out dimensions: size of 640x480, 16bpp
    m_ppData_TV.outputSize.height = m_ppData_TV.inputSize.width * 2;
    m_ppData_TV.outputSize.width = m_ppData_TV.inputSize.height * 2;
    m_ppData_TV.outputStride = 640 * 2;

    m_ppData_TV.directDisplay = FALSE;

    return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -