basesurf.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:144k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: basesurf.cpp,v 1.11.4.3 2004/07/26 10:27:38 pankajgupta Exp $
  3.  *
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  *
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  *
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  *
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  *
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  *
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  *
  46.  * Contributor(s):
  47.  *
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxcom.h"
  50. #include "hxtypes.h"
  51. #include "hxwintyp.h"
  52. #include "hxvsurf.h"
  53. #include "hxslist.h"
  54. #include "hxthread.h"
  55. #include "hxver.h"
  56. #if defined(_WINDOWS)
  57. #include "winsurf.h"
  58. #if defined (HELIX_FEATURE_VS2)
  59. #include "winsurf2.h"
  60. #endif
  61. #include "winroot.h"    // must be included before colormap.h
  62. #endif
  63. #include "region.h"
  64. #include "basesurf.h"
  65. #include "basesite.h"
  66. #include "baseroot.h"
  67. #include "hxprefs.h"
  68. #include "hxtick.h"
  69. #include "hxheap.h"
  70. #include "colormap.h"
  71. #include "microsleep.h"
  72. #include "hxevent.h"
  73. #include "infmt.h"
  74. //MMX alphablending only available on linux and windows right now.
  75. //Should work just fine on any IA plaform though (intel solaris for example)
  76. #ifdef _USE_MMX
  77. #include "mmx_util.h" //for checkMmxAvailablity()
  78. extern "C"
  79. {
  80.     void AlphaBlendMMX( UINT32*, UINT32*, INT32 );
  81. }
  82. #endif
  83. #include <math.h>  // fabs()
  84. #include "drawline.h"
  85. #if defined(_UNIX) && !defined(_MAC_UNIX)
  86. #  include "unixsurf.h"
  87. #endif
  88. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  89. //#include "../dcondev/dcon.h"
  90. #include "platform/mac/macsurf.h"
  91. #endif
  92. #ifdef _DEBUG
  93. #undef HX_THIS_FILE
  94. static const char HX_THIS_FILE[] = __FILE__;
  95. #endif
  96. #ifdef _DEBUG
  97. #include "region.h" //just for _DumpString
  98. #endif
  99. #include "sitefact.h"
  100. #include "hwmemobj.h"
  101. #define NOT_IMPL    0
  102. /*
  103.  *  Defines used for testing various parts of the code.
  104.  */
  105. //#define _CHECK_PERFORMANCE
  106. //#define _CHECK_SCROLLBARS
  107. //#define _CHECK_MODES
  108. #define NOT_IMPL 0
  109. #define OVERLAY_BYPASS_THRESHOLD 8
  110. #define OVERLAY_FAILURE_THRESHOLD 3 // What the heck should this number be? Does it really matter?
  111. CBaseSurface::CBaseSurface(IUnknown* pContext, CHXBaseSite* pSite)
  112.     : m_lRefCount(0)
  113.     , m_pContext(pContext)
  114.     , m_Brightness(0)
  115.     , m_Contrast(0)
  116.     , m_Saturation(0)
  117.     , m_Hue(0)
  118.     , m_Sharpness(0)
  119.     , m_ModeSharpness(0)
  120.     , m_PrevBrightness(0)
  121.     , m_PrevContrast(0)
  122.     , m_PrevSaturation(0)
  123.     , m_PrevHue(0)
  124.     , m_PrevSharpness(0)
  125.     , m_pSite(pSite)
  126.     , m_pRootSurface(NULL)
  127.     , m_pOptimizedFormat(NULL)
  128.     , m_nSrcCID(0)
  129.     , m_nBltMode(HX_BASIC_BLT)
  130.     , m_nSurfaceCID(0)
  131.     , m_bBackGroundDirty(TRUE)
  132.     , m_fScrollBarZoom(1.0)
  133.     , zm_pColorAcc(NULL)
  134.     , m_pyuvInputMngr(NULL)
  135.     , m_pHwMemObj(NULL)
  136.     , m_pucLastImage(NULL)
  137.     , m_ulLastBlendTime(0)
  138.     , m_bSpamUpdateOverlay(TRUE)
  139.     , m_bFlipOverlay(FALSE)
  140.     , m_nBackBufferCount(0)
  141.     , m_nMaxBackBuffers(3)
  142.     , m_bDisableFillColorKey(TRUE)
  143.     , m_bMultipleOverlay(FALSE)
  144.     , m_nOldBltMode(0)
  145.     , m_nOldBltMode2(0)
  146.     , m_oldOverlayColorDepth(0)
  147.     , m_convertedOverlayColor(0x00010203)
  148.     , m_bUseOverlays(TRUE)
  149.     , m_nOverlayFailureCount(0)
  150.     , m_nDDSurfaceSize(0)
  151.     , m_nUpdateOverlayByPassCount(0)
  152.     , m_scaleFactorX(1.0)
  153.     , m_scaleFactorY(1.0)
  154.     , m_paSrcRects(NULL)
  155.     , m_paDestRects(NULL)
  156.     , m_pAdditionalColorKey(NULL)
  157.     , m_bNeedColorKeyFilled(FALSE)
  158.     , m_bYUVBlending(FALSE)
  159.     , m_bVideoSurface2(FALSE)
  160.     , m_bOptimalVideoScheduler(FALSE)
  161.     , m_pLinkedOverlay(NULL)
  162.     , m_bAllowOverlayLinking(TRUE)
  163.     , m_bLostHWAcceleration(FALSE)
  164.     , m_bOffBecauseofShinking(FALSE)
  165.     , m_bImageBlocksGood(FALSE)
  166.     , m_pOverlayManager(NULL)
  167. {
  168.     HX_ASSERT( m_pContext );
  169.     m_pContext->AddRef();
  170.     memset( &m_bmiLastImage, 0, sizeof( HXBitmapInfoHeader ) );
  171.     memset( &m_bmiLastBlt, 0, sizeof( HXBitmapInfoHeader ) );
  172.     memset( &m_surfaceSize, 0, sizeof(HXxSize) );
  173.     memset( &m_lastUpdateDestRect, 0, sizeof(m_lastUpdateDestRect) );
  174.     memset( &m_lastUpdateSrcRect, 0, sizeof(m_lastUpdateSrcRect) );
  175.     memset( &m_lastSrcRect, 0, sizeof(m_lastSrcRect) );
  176.     memset( &m_bmi, 0, sizeof(m_bmi) );
  177. #if !defined(_GOLD) && 0
  178.     m_TimeStamps.Init(m_pContext, this);
  179. #endif
  180.     IHXPreferences*    pPreferences    = NULL;
  181.     IHXBuffer*         pBuffer         = NULL;
  182.     if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
  183.     {
  184.         if (pPreferences->ReadPref("SiteZoomFactor", pBuffer) == HXR_OK)
  185.         {
  186.             m_fScrollBarZoom = !(::atoi((char*) pBuffer->GetBuffer()) == 1);
  187.         }
  188.         HX_RELEASE(pBuffer);
  189.         if (pPreferences->ReadPref("UseOverlay", pBuffer) == HXR_OK)
  190.         {
  191.             m_bUseOverlays = ::atoi((char*) pBuffer->GetBuffer()) == 1;
  192.         }
  193.         HX_RELEASE(pBuffer);
  194.         if (pPreferences->ReadPref("SpamUpdateOverlay", pBuffer) == HXR_OK)
  195.         {
  196.             m_bSpamUpdateOverlay = ::atoi((char*) pBuffer->GetBuffer()) == 1;
  197.         }
  198.         HX_RELEASE(pBuffer);
  199.         if (pPreferences->ReadPref("FlipOverlay", pBuffer) == HXR_OK)
  200.         {
  201.             m_bFlipOverlay = ::atoi((char*) pBuffer->GetBuffer()) == 1;
  202.         }
  203.         HX_RELEASE(pBuffer);
  204.         if (pPreferences->ReadPref("YUY2First", pBuffer) == HXR_OK)
  205.         {
  206.             if (::atoi((char*) pBuffer->GetBuffer()) == 1)
  207.             {
  208.                 int list[] = {0,3,1,4};
  209.                 m_pyuvInputMngr->SetOutputPriority(CID_I420, list, 4);
  210.             }
  211.         }
  212.         HX_RELEASE(pBuffer);
  213.         if (pPreferences->ReadPref("LinkOverlays", pBuffer) == HXR_OK)
  214.         {
  215.             m_bAllowOverlayLinking = ::atoi((char*) pBuffer->GetBuffer()) == 1;
  216.         }
  217.         HX_RELEASE(pBuffer);
  218.         m_pContext->QueryInterface(IID_IHXOverlayManager, (void**)&m_pOverlayManager);
  219.     }
  220.     HX_RELEASE(pPreferences);
  221. #ifdef _DEBUG
  222.     const char* szKeyName = "Software\"HXVER_COMMUNITY"\Debug\SetHook";
  223.     m_bAllocHook = HXDebugOptionEnabled(szKeyName);
  224. #endif
  225. }
  226. CBaseSurface::~CBaseSurface()
  227. {
  228.     HX_DELETE(zm_pColorAcc);
  229.     HX_DELETE(m_pyuvInputMngr);
  230.     HX_DELETE(m_pHwMemObj);
  231.     HX_RELEASE(m_pRootSurface);
  232.     // CBaseSite::Destroy calls EndOptimizedBlt.  We can't call
  233.     // EndOptimizedBlt from the destructor since it calls DestroySurfaces
  234.     // which calls _ReleaseSurface which is a pure virtual...the derived
  235.     // class was already destoryed.
  236.     HX_ASSERT(!m_pOptimizedFormat);
  237.     HX_RELEASE(m_pContext);
  238.     HX_FREE(m_pucLastImage);
  239.     memset( &m_bmiLastImage, 0, sizeof( m_bmiLastImage ) );
  240.     memset( &m_bmiLastBlt, 0, sizeof( m_bmiLastBlt ) );
  241.     HX_FREE( m_paSrcRects );
  242.     HX_FREE( m_paDestRects );
  243.     //Clean up alphablending YUVA image list
  244.     CHXMapPtrToPtr::Iterator i = m_YUVAImageList.Begin();
  245.     while(i != m_YUVAImageList.End())
  246.     {
  247.         Image* pImage = (Image*)*i;
  248.         HX_VECTOR_DELETE(pImage->pucImage);
  249.         HX_DELETE(pImage);
  250.         ++i;
  251.     }
  252.     m_YUVAImageList.RemoveAll();
  253.     CHXSimpleList::Iterator j = m_imageBlocks.Begin();
  254.     m_bImageBlocksGood = FALSE;
  255.     while(j != m_imageBlocks.End())
  256.     {
  257.         ImageBlock* pBlock = (ImageBlock*)*j;
  258.         Image* pImage = pBlock->pImage;
  259.         HX_FREE(pImage->pucImage);
  260.         HX_DELETE(pImage);
  261.         HX_DELETE(pBlock);
  262.         ++j;
  263.     }
  264.     m_imageBlocks.RemoveAll();
  265.     if (m_pOverlayManager)
  266.     {
  267.         m_pOverlayManager->RemoveOverlayRequest((IHXOverlayResponse*)this);
  268.     }
  269.     HX_RELEASE(m_pOverlayManager);
  270.     HXDestroyRegion(m_pAdditionalColorKey);
  271.     m_pAdditionalColorKey = NULL;
  272.     m_LinkedSites.RemoveAll();
  273. }
  274. void CBaseSurface::SetRootSurface( CBaseRootSurface* pSurface)
  275. {
  276.     m_pRootSurface = pSurface;
  277.     pSurface->AddRef();
  278. }
  279. void CBaseSurface::DestroySurfaces()
  280. {
  281.     if (m_surfaceSize.cx || m_surfaceSize.cy)
  282.     {
  283.         CBaseRootSurface* pSurface = m_pSite->GetRootSurface();
  284.         // XXXAH huh?  Should this not be releasing it's own internal
  285.         //             surface?  Again, minimal Changes.
  286.         //XXXgfw not to mention that you can't call this from the dtor
  287.         //of this class like is happening. Lets make sure that whatever
  288.         //is needed happens when the root surface is deleted.
  289.         if (pSurface)
  290.         {
  291.             _ReleaseSurface(pSurface);
  292.         }
  293.         ::memset(&m_surfaceSize, 0, sizeof(m_surfaceSize));
  294.     }
  295.     HX_DELETE(m_pHwMemObj);
  296. }
  297. void CBaseSurface::ReInitSurfaces()
  298. {
  299.     if (m_pOptimizedFormat)
  300.     {
  301.         HXBitmapInfoHeader optFormat;
  302.         memcpy(&optFormat, m_pOptimizedFormat, sizeof(HXBitmapInfoHeader)); /* Flawfinder: ignore */
  303.         memset(&m_surfaceSize, 0, sizeof(HXxSize));
  304.         BeginOptimizedBlt(&optFormat);
  305.     }
  306. }
  307. BOOL CBaseSurface::ForceGDIMode(BOOL bForceGDI)
  308. {
  309.     if(bForceGDI)
  310.     {
  311.         if (m_nBltMode == HX_OVERLAY_BLT)
  312.         {
  313.             m_nBltMode = HX_BASIC_BLT;
  314. #if defined(_UNIX) && !defined(_MAC_UNIX)
  315.             _ReleaseSurface();
  316. #endif
  317.             m_pSite->InternalForceRedraw();
  318.             m_pSite->m_pTopLevelSite->ScheduleCallback(CLIP, 0 );
  319.             m_nOldBltMode = HX_OVERLAY_BLT;
  320.         }
  321.     }
  322.     else
  323.     {
  324.         if (m_nOldBltMode == HX_OVERLAY_BLT)
  325.         {
  326.             m_nBltMode = HX_OVERLAY_BLT;
  327. #if defined(_UNIX) && !defined(_MAC_UNIX)
  328.             TryCreateOverlay(TRUE);
  329. #endif
  330.             m_pSite->InternalForceRedraw();
  331.             m_pSite->m_pTopLevelSite->ScheduleCallback(CLIP, 0 );
  332.             FillColorKey();
  333.             m_nOldBltMode = HX_BASIC_BLT;
  334.             m_bOffBecauseofShinking = FALSE;
  335.         }
  336.     }
  337.     return TRUE;
  338. }
  339. /************************************************************************
  340.  *  Method:
  341.  *    IUnknown::QueryInterface
  342.  */
  343. STDMETHODIMP CBaseSurface::QueryInterface(REFIID riid, void** ppvObj)
  344. {
  345.     if (IsEqualIID(riid, IID_IHXVideoSurface))
  346.     {
  347.         AddRef();
  348.         *ppvObj = (IUnknown*)(IHXVideoSurface*)this;
  349.         return HXR_OK;
  350.     }
  351.     else if (IsEqualIID(riid, IID_IUnknown))
  352.     {
  353.         AddRef();
  354.         *ppvObj = (IUnknown*)(IHXSite*)this;
  355.         return HXR_OK;
  356.     }
  357.     else if (IsEqualIID(riid, IID_IHXVideoControl))
  358.     {
  359.         AddRef();
  360.         *ppvObj = (IUnknown*)(IHXVideoControl*)this;
  361.         return HXR_OK;
  362.     }
  363.     else if (IsEqualIID(riid, IID_IHXOverlayResponse))
  364.     {
  365.         AddRef();
  366.         *ppvObj = (IUnknown*)(IHXOverlayResponse*)this;
  367.         return HXR_OK;
  368.     }
  369.     *ppvObj = NULL;
  370.     return HXR_NOINTERFACE;
  371. }
  372. /************************************************************************
  373.  *  Method:
  374.  *    IUnknown::AddRef
  375.  */
  376. STDMETHODIMP_(ULONG32) CBaseSurface::AddRef()
  377. {
  378.     return InterlockedIncrement(&m_lRefCount);
  379. }
  380. /************************************************************************
  381.  *  Method:
  382.  *    IUnknown::Release
  383.  */
  384. STDMETHODIMP_(ULONG32) CBaseSurface::Release()
  385. {
  386.     if (InterlockedDecrement(&m_lRefCount) > 0)
  387.     {
  388.         return m_lRefCount;
  389.     }
  390.     delete this;
  391.     return 0;
  392. }
  393. BOOL  CBaseSurface::IsPixelTransparent(HXxPoint& point, INT32 nAlphaLevel )
  394. {
  395.     BOOL      retVal = FALSE;
  396.     INT32     nCID   = -1;
  397.     INT32     nPitch = 0;
  398.     HXxPoint  origin = *(m_pSite->GetOrigin());
  399.     //It can only be transparent if we are blt'ing ARGB32.
  400.     nCID   = GETBITMAPCOLOR(&m_bmiLastBlt);
  401.     nPitch = GETBITMAPPITCH(&m_bmiLastImage);
  402.     if( nCID == CID_ARGB32 )
  403.     {
  404.         if( m_pucLastImage )
  405.         {
  406.             UINT32* pPixel=NULL;
  407.             if( nPitch<0 )
  408.             {
  409.                 pPixel = (UINT32*)(m_pucLastImage+m_bmiLastImage.biSizeImage+nPitch);
  410.                 pPixel -= (point.y-origin.y)*m_bmiLastImage.biWidth - (point.x-origin.x);
  411.             }
  412.             else
  413.             {
  414.                 pPixel = (UINT32*)m_pucLastImage;
  415.                 pPixel += (point.y-origin.y)*m_bmiLastImage.biWidth + (point.x-origin.x);
  416.             }
  417.             if( pPixel>=(UINT32*)m_pucLastImage &&
  418.                 pPixel<(UINT32*)(m_pucLastImage+m_bmiLastImage.biSizeImage))
  419.             {
  420.                 int alpha = (*pPixel&0xff000000)>>24;
  421.                 if( alpha > nAlphaLevel )
  422.                 {
  423.                     retVal = TRUE;
  424.                 }
  425.             }
  426.         }
  427.     }
  428.     return retVal;
  429. }
  430. void CBaseSurface::_AlphaBlend( HXREGION*              pRegionToBlend,
  431.                                 UCHAR*               pBottomImage,
  432.                                 HXBitmapInfoHeader* pbmiBottomImageInfo,
  433.                                 HXxPoint*            pBottomPosition,
  434.                                 UCHAR*               pTopImage,
  435.                                 HXBitmapInfoHeader* pbmiTopImageInfo,
  436.                                 HXxPoint*            pTopPosition
  437.                                 )
  438. {
  439. #ifdef _USE_MMX
  440.     static const BOOL bMMXAvailable = (checkMmxAvailablity()&CPU_HAS_MMX)?1:0;
  441. #else
  442.     static const BOOL bMMXAvailable = FALSE;
  443. #endif
  444. #if defined(_DEBUG) && 0
  445.     _DumpRegion(pRegionToBlend);
  446. #endif
  447.     if( pBottomImage == NULL || pTopImage == NULL )
  448.     {
  449.         return;
  450.     }
  451.     //Make sure we only try to alpha blend ARGB32 content.
  452.     int nCIDBottom   = GETBITMAPCOLOR( pbmiBottomImageInfo );
  453.     int nCIDTop      = GETBITMAPCOLOR( pbmiTopImageInfo );
  454.     int nBottomPitch = GETBITMAPPITCH( pbmiBottomImageInfo );
  455.     int nTopPitch    = GETBITMAPPITCH( pbmiTopImageInfo );
  456.     if( nCIDTop != CID_ARGB32 || (nCIDBottom!=CID_ARGB32 && nCIDBottom!=CID_RGB32) )
  457.     {
  458.         HX_ASSERT( "Trying to alphablend unsupported type." );
  459.         return;
  460.     }
  461.     BOOL  bFade=FALSE;
  462.     int   completeness = 0;
  463.     if( (m_pSite->m_fpTransitionEffect == Crossfade ||
  464.          m_pSite->m_fpTransitionEffect == FadeToColor ||
  465.          m_pSite->m_fpTransitionEffect == FadeFromColor )
  466.         && m_pSite->m_nTransitionState!= 1000 )
  467.     {
  468.         completeness = m_pSite->m_nTransitionState;
  469.         if((m_pSite->m_fpTransitionEffect != Crossfade &&
  470.             m_pSite->m_bTransitionReversed) ||
  471.            (m_pSite->m_fpTransitionEffect == Crossfade &&
  472.             (!m_pSite->m_bTransitionTranIn ^
  473.              m_pSite->m_bTransitionReversed)))
  474.         {
  475.             completeness = 1000 - completeness;
  476.         }
  477.         if( m_pSite->m_fpTransitionEffect== FadeFromColor)
  478.         {
  479.             completeness = 1000 - completeness;
  480.         }
  481.         //Map [0,1000] --> [0,1024] for fixed point fade math.
  482.         completeness = (int)((float)completeness*1024.0/1000.0);
  483.         bFade=TRUE;
  484.     }
  485.     if( !HXEmptyRegion(pRegionToBlend) )
  486.     {
  487.         int nBottomOffset = 0;
  488.         int nTopOffset    = 0;
  489.         int nBotPosX      = 0;
  490.         int nBotPosY      = 0;
  491.         int nTopPosX      = 0;
  492.         int nTopPosY      = 0;
  493.         for(int i =0; i< pRegionToBlend->numRects; i++)
  494.         {
  495.             //We need to alpha blend each rect in the region.
  496.             int topX=0, topY = 0;
  497.             int botX=0, botY = 0;
  498.             topX = pRegionToBlend->rects[i].x1;
  499.             topY = pRegionToBlend->rects[i].y1;
  500.             botX = pRegionToBlend->rects[i].x2;
  501.             botY = pRegionToBlend->rects[i].y2;
  502.             if( nBottomPitch<0 )
  503.                 nBottomOffset = -(pbmiBottomImageInfo->biWidth+(botX-topX));
  504.             else
  505.                 nBottomOffset = pbmiBottomImageInfo->biWidth-(botX-topX);
  506.             if( nTopPitch<0 )
  507.                 nTopOffset = -(pbmiTopImageInfo->biWidth+(botX-topX));
  508.             else
  509.                 nTopOffset = pbmiTopImageInfo->biWidth-(botX-topX);
  510.             nTopPosX = pTopPosition->x;
  511.             nTopPosY = pTopPosition->y;
  512.             nBotPosX = pBottomPosition->x;
  513.             nBotPosY = pBottomPosition->y;
  514.             //blend this rect.
  515.             UINT32* pulBotPixel=NULL;
  516.             UINT32* pulTopPixel=NULL;
  517.             if( nBottomPitch<0 )
  518.             {
  519.                 pulBotPixel = (UINT32*)(pBottomImage+pbmiBottomImageInfo->biSizeImage+nBottomPitch);
  520.                 pulBotPixel -= ((topY-nBotPosY)*pbmiBottomImageInfo->biWidth - (topX-nBotPosX));
  521.             }
  522.             else
  523.             {
  524.                 pulBotPixel = (UINT32*)pBottomImage;
  525.                 pulBotPixel += ((topY-nBotPosY)*pbmiBottomImageInfo->biWidth + (topX-nBotPosX));
  526.             }
  527.             if( nTopPitch<0 )
  528.             {
  529.                 pulTopPixel = (UINT32*)(pTopImage+pbmiTopImageInfo->biSizeImage+nTopPitch);
  530.                 pulTopPixel -= ((topY-nTopPosY)*pbmiTopImageInfo->biWidth    - (topX-nTopPosX));
  531.             }
  532.             else
  533.             {
  534.                 pulTopPixel = (UINT32*)pTopImage;
  535.                 pulTopPixel += ((topY-nTopPosY)*pbmiTopImageInfo->biWidth    + (topX-nTopPosX));
  536.             }
  537.             int alpha     = 0;
  538.             int alphasave = 0;
  539.             for( int y=topY ; y<=botY-1 ; y++ )
  540.             {
  541.                 //XXXgfw this blows! We need a version of our MMX version
  542.                 //for doing fades as well.
  543.                 if( !bMMXAvailable || bFade )
  544.                 {
  545.                     for( int x=topX ; x<=botX-1 ; x++ )
  546.                     {
  547.                         //Blend it.
  548.                         //We *MUST* preserve the alpha channel in the top image.
  549.                         //This is needed for hit testing on transparent pixels.
  550.                         if( !bFade )
  551.                         {
  552.                             alpha = 255-((*pulTopPixel & 0xff000000)>>24);
  553.                             alphasave = *pulTopPixel & 0xff000000;
  554.                             alpha = alpha>128 ? alpha + 1 : alpha;
  555.                         }
  556.                         else
  557.                         {
  558.                             if( m_pSite->m_fpTransitionEffect == Crossfade )
  559.                             {
  560.                                 //fixed point version of (comp/1000 * alpha )
  561.                                 alpha = (*pulTopPixel & 0xff000000)>>24;
  562.                                 if( GETBITMAPCOLOR(&m_bmiLastBlt) != CID_ARGB32 )
  563.                                     alpha = 0x00;
  564.                                 alpha = ((completeness*(255-alpha)+512))>>10;
  565.                                 alphasave = (255-alpha)<<24;
  566.                             }
  567.                             else if( m_pSite->m_fpTransitionEffect == FadeToColor ||
  568.                                      m_pSite->m_fpTransitionEffect == FadeFromColor)
  569.                             {
  570.                                 //Not only affect alpha but also fading to color.
  571.                                 alpha = (completeness*255+512)>>10;
  572.                                 UINT32 fadeColor = (m_pSite->m_ulTransitionFadeColor&0x00ffffff)|(alpha<<24);
  573.                                 int a1 = 255-((*pulTopPixel&0xff000000)>>24);
  574.                                 *pulTopPixel =
  575.                                     (((alpha*( (fadeColor&0x00ff0000)-(*pulTopPixel&0x00ff0000))+((*pulTopPixel&0x00ff0000)<<8))>>8)&0x00ff0000)|
  576.                                     (((alpha*( (fadeColor&0x0000ff00)-(*pulTopPixel&0x0000ff00))+((*pulTopPixel&0x0000ff00)<<8))>>8)&0x0000ff00)|
  577.                                     (((alpha*( (fadeColor&0x000000ff)-(*pulTopPixel&0x000000ff))+((*pulTopPixel&0x000000ff)<<8))>>8)&0x000000ff);
  578.                                 if( alpha<a1 )
  579.                                     alpha = a1;
  580.                                 //Now make sure the rest of the blending uses the
  581.                                 //new alpha channel from the FadeToColor state.
  582.                                 alphasave = *pulTopPixel & ((255-alpha)<<24);
  583.                                 //OK, we never alpha blend if a renderer outputs in plain old
  584.                                 //RGB, only if they output in ARGB. Now, some renderer blt'ing in
  585.                                 //RGB32 output random numbers, all zeros or all 0xFF in the alpha
  586.                                 //channel. That can screw us up, so we will just set it here to not
  587.                                 //have an alpha channel.
  588.                                 if( GETBITMAPCOLOR(&m_bmiLastBlt) != CID_ARGB32 )
  589.                                     alpha = 0xFF;
  590.                             }
  591.                         }
  592.                         *pulTopPixel =
  593.                             (((alpha*( (*pulTopPixel&0x00ff0000)-(*pulBotPixel&0x00ff0000))+((*pulBotPixel&0x00ff0000)<<8))>>8)&0x00ff0000)|
  594.                             (((alpha*( (*pulTopPixel&0x0000ff00)-(*pulBotPixel&0x0000ff00))+((*pulBotPixel&0x0000ff00)<<8))>>8)&0x0000ff00)|
  595.                             (((alpha*( (*pulTopPixel&0x000000ff)-(*pulBotPixel&0x000000ff))+((*pulBotPixel&0x000000ff)<<8))>>8)&0x000000ff);
  596.                         *pulTopPixel = *pulTopPixel|alphasave;
  597.                         //Next pixel
  598.                         pulBotPixel++;
  599.                         pulTopPixel++;
  600.                     }
  601.                     //Next row.
  602.                     pulBotPixel += nBottomOffset;
  603.                     pulTopPixel += nTopOffset;
  604.                 }
  605.                 else
  606.                 {
  607. #ifdef _USE_MMX
  608.                     //Use MMX version of blender
  609.                     AlphaBlendMMX( pulTopPixel,
  610.                                    pulBotPixel,
  611.                                    (botX-topX)
  612.                                    );
  613.                     //Next row.
  614.                     pulBotPixel += nBottomOffset+(botX-topX);
  615.                     pulTopPixel += nTopOffset+(botX-topX);
  616. #endif
  617.                 }
  618.             }
  619. #ifdef _USE_MMX
  620.             //Do our emms instruction here so we don't have do it each
  621.             //line. It is a expensive operation.
  622. #ifdef _WIN32
  623.             __asm emms
  624. #elif defined(_LINUX)
  625.                 __asm__ __volatile__ ( "emms" );
  626. #endif
  627. #endif
  628.         }
  629.     }
  630. }
  631. #if 0
  632. void CBaseSurface::DrawCheckerBoard(UCHAR *pY, UCHAR *pU, UCHAR *pV,
  633.                                     INT32 nYPitch, INT32 nUPitch, INT32 nVPitch,
  634.                                     INT32 nImageWidth, INT32 nImageHeight)
  635. {
  636.     const int COLS = 5;
  637.     const int ROWS = 5;
  638.     int Y[2] = {255, 0};
  639.     int Cb = 128;
  640.     int Cr = 128;
  641.     int nColWidth = nImageWidth/COLS;
  642.     int nRowWidth = nImageHeight/ROWS;
  643.     IHXPreferences* pPreferences = NULL;
  644.     IHXBuffer* pBuffer = NULL;
  645.     if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
  646.     {
  647.         if (pPreferences->ReadPref("VideoBoost\Y0", pBuffer) == HXR_OK)
  648.         {
  649.             Y[0] = ::atoi((char*) pBuffer->GetBuffer());
  650.             HX_RELEASE(pBuffer);
  651.         }
  652.         if (pPreferences->ReadPref("VideoBoost\Y1", pBuffer) == HXR_OK)
  653.         {
  654.             Y[1] = ::atoi((char*) pBuffer->GetBuffer());
  655.             HX_RELEASE(pBuffer);
  656.         }
  657.         if (pPreferences->ReadPref("VideoBoost\Cb", pBuffer) == HXR_OK)
  658.         {
  659.             Cb = ::atoi((char*) pBuffer->GetBuffer());
  660.             HX_RELEASE(pBuffer);
  661.         }
  662.         if (pPreferences->ReadPref("VideoBoost\Cr", pBuffer) == HXR_OK)
  663.         {
  664.             Cr = ::atoi((char*) pBuffer->GetBuffer());
  665.             HX_RELEASE(pBuffer);
  666.         }
  667.         HX_RELEASE(pPreferences);
  668.     }
  669.     UCHAR* pTemp = pY;
  670.     for (int i=0; i<nImageHeight; i++)
  671.     {
  672.         // Draw a line of y for each column
  673.         for (int j=0; j<COLS; j++)
  674.         {
  675.             memset(pTemp, Y[j%2], nColWidth);
  676.             pTemp += nColWidth;
  677.         }
  678.         // Move y pointer to next row
  679.         pTemp = pY + nYPitch*(i+1);
  680.         // Swap y colors at each new row
  681.         if (i%nRowWidth == 0)
  682.         {
  683.             int nTemp = Y[0];
  684.             Y[0] = Y[1];
  685.             Y[1] = nTemp;
  686.         }
  687.     }
  688.     // Draw the Cr and Cb planes
  689.     memset(pU, Cb, nImageWidth*nImageHeight/4);
  690.     memset(pV, Cr, nImageWidth*nImageHeight/4);
  691. }
  692. #endif //0
  693. HXREGION* CBaseSurface::_DetermineBestRegion()
  694. {
  695.     HXRECTANGLE rect;
  696.     ImageBlock* pBlock = NULL;
  697.     //Create a region from out image block list.
  698.     HXREGION* pRetReg = HXCreateRegion();
  699.     CHXSimpleList::Iterator j = m_imageBlocks.Begin();
  700.     while(j != m_imageBlocks.End())
  701.     {
  702.         pBlock = (ImageBlock*)*j;
  703.         rect.x      = (short)pBlock->rect.left;
  704.         rect.y      = (short)pBlock->rect.top;
  705.         rect.width  = (short)(pBlock->rect.right-pBlock->rect.left);
  706.         rect.height = (short)(pBlock->rect.bottom-pBlock->rect.top);
  707.         HXUnionRectWithRegion( &rect, pRetReg, pRetReg );
  708.         ++j;
  709.     }
  710.     return pRetReg;
  711. }
  712. void CBaseSurface::_RemoveYUVImageLists()
  713. {
  714.     m_pSite->_TLSLock();
  715.     CHXSimpleList::Iterator jj = m_imageBlocks.Begin();
  716.     while(jj != m_imageBlocks.End())
  717.     {
  718.         ImageBlock* pXBlock = (ImageBlock*)*jj;
  719.         Image* pXTmp = pXBlock->pImage;
  720.         HX_FREE(pXTmp->pucImage);
  721.         HX_DELETE(pXTmp);
  722.         HX_DELETE(pXBlock);
  723.         ++jj;
  724.     }
  725.     m_imageBlocks.RemoveAll();
  726.     m_bImageBlocksGood = FALSE;
  727.     CHXMapPtrToPtr::Iterator i = m_YUVAImageList.Begin();
  728.     while(i != m_YUVAImageList.End())
  729.     {
  730.         Image* pImage = (Image*)*i;
  731.         HX_DELETE(pImage->pucImage);
  732.         HX_DELETE(pImage);
  733.         ++i;
  734.     }
  735.     m_YUVAImageList.RemoveAll();
  736.     m_pSite->_TLSUnlock();
  737. }
  738. CHXBaseSite* CBaseSurface::_SearchForYUV(CHXBaseSite* pTopSite)
  739. {
  740.     HX_ASSERT( pTopSite );
  741.     CHXBaseSite* pRetSite = NULL;
  742.     CHXMapPtrToPtr::Iterator i;
  743.     CBaseSurface* pSurf = pTopSite->m_pVideoSurface;
  744.     if( pSurf )
  745.     {
  746.         int nCID2 = GETBITMAPCOLOR(&(pSurf->m_bmiLastBlt));
  747.         if( IsYUV(nCID2) && pSurf->_IsDisplaySurfaceYuv())
  748.         {
  749.             pRetSite = pTopSite;
  750.         }
  751.     }
  752.     if( !pRetSite )
  753.     {
  754.         //If the one passed in isn't any good, we need to go through its
  755.         //lists of alphablend sites and so on.
  756.         for( i=pTopSite->m_AlphaBlendSites.Begin() ;
  757.              i!=pTopSite->m_AlphaBlendSites.End() && !pRetSite ;
  758.              ++i)
  759.         {
  760.             CHXBaseSite* pSite = (CHXBaseSite*) i.get_key();
  761.             pRetSite = _SearchForYUV( pSite );
  762.         }
  763.     }
  764.     return pRetSite;
  765. }
  766. BOOL CBaseSurface::_BlendYUVRects( AlphaStruct* pList, int nCount, UINT32 ulDestFourCC)
  767. {
  768.     BOOL bBlend = TRUE;
  769.     //These rects in pList *must* match the ones in m_imageBlocks.
  770.     //If they don't, time for recompute clip again.
  771.     CHXSimpleList::Iterator g = m_imageBlocks.Begin();
  772.     int i=0;
  773.     while(g != m_imageBlocks.End() )
  774.     {
  775.         ImageBlock*   pBlockOut = (ImageBlock*)*g;
  776.         Image*        pImageOut = pBlockOut->pImage;
  777.         CHXBaseSite*  pSite     = pBlockOut->pSrcSite;
  778.         Image*        pImage    = NULL;
  779.         //Find ourselves in that site's YUV list.
  780.         CHXBaseSite* pTmp = NULL;
  781.         CHXMapPtrToPtr::Iterator j = pSite->m_pVideoSurface->m_YUVAImageList.Begin();
  782.         while( j!=pSite->m_pVideoSurface->m_YUVAImageList.End() )
  783.         {
  784.             pTmp = (CHXBaseSite*)j.get_key();
  785.             if( pTmp == m_pSite )
  786.             {
  787.                 pImage = (Image*)*j;
  788.                 break;
  789.             }
  790.             ++j;
  791.         }
  792.         //HX_ASSERT( pImage );
  793.         if( pImage)
  794.         {
  795.             //Blend pList[i] under AYUV and put in pTmp
  796.             int nSizeX = pBlockOut->rect.right-pBlockOut->rect.left;
  797.             int nSizeY = pBlockOut->rect.bottom-pBlockOut->rect.top;
  798.             //int nPImageDataPitch = GETBITMAPPITCH(pList[i].lPitch);
  799.             int nPImageOutPitch  = GETBITMAPPITCH(&pImageOut->bmiImage);
  800.             int nPImagePitch     = GETBITMAPPITCH(&pImage->bmiImage);
  801.             // These rects should match...might crash if they don't
  802.             if( nSizeX > pImage->bmiImage.biWidth ||
  803.                 nSizeX > pImageOut->bmiImage.biWidth ||
  804.                 nSizeX > HXxRECT_WIDTH(pList[i].rcImageRect) )
  805.             {
  806.                 bBlend = FALSE;
  807.             }
  808.             if( nSizeY > pImage->bmiImage.biHeight ||
  809.                 nSizeY > pImageOut->bmiImage.biHeight ||
  810.                 nSizeY > HXxRECT_HEIGHT(pList[i].rcImageRect) )
  811.             {
  812.                 bBlend = FALSE;
  813.             }
  814.             if( pBlockOut->startX<0 || pBlockOut->startY<0 )
  815.             {
  816.                 bBlend = FALSE;
  817.             }
  818.             if (bBlend)
  819.             {
  820.                 HX_RESULT hr = zm_pColorAcc->I420andYUVA(
  821.                     pList[i].pBuffer,
  822.                     pList[i].ulImageWidth, pList[i].ulImageHeight,
  823.                     pList[i].lPitch,
  824.                     pList[i].rcImageRect.left,
  825.                     pList[i].rcImageRect.top,
  826.                     //pBlockOut->rect.left, pBlockOut->rect.top,
  827.                     pImage->pucImage,
  828.                     pImage->bmiImage.biWidth, pImage->bmiImage.biHeight,
  829.                     nPImagePitch,
  830.                     pBlockOut->startX, pBlockOut->startY,
  831.                     pImageOut->pucImage,
  832.                     pImageOut->bmiImage.biWidth, pImageOut->bmiImage.biHeight,
  833.                     nPImageOutPitch,
  834.                     0, 0,
  835.                     nSizeX, nSizeY,
  836.                     MapFourCCtoCID(ulDestFourCC)
  837.                     );
  838.                 bBlend = hr==HXR_OK;
  839.                 //Now keep drawing up the line through all
  840.                 //overlapping ARGB images.
  841.                 pSite->m_pVideoSurface->_RecursiveYUVBlend( pImageOut,
  842.                                                             pBlockOut->rect,
  843.                                                             this, 0, 0);
  844.             }
  845.             i++;
  846.         }
  847.         ++g;
  848.     }
  849.     return bBlend;
  850. }
  851. BOOL CBaseSurface::_DoYUVRectsIntersect()
  852. {
  853.     BOOL bBlend = FALSE;
  854.     CHXMapPtrToPtr::Iterator i;
  855.     while( i != m_pSite->m_AlphaBlendNotifiers.End() && !bBlend )
  856.     {
  857.         CHXBaseSite* pSite = (CHXBaseSite*)*i;
  858.         if( pSite->m_AlphaBlendNotifiers.GetCount() )
  859.         {
  860.             bBlend = TRUE;
  861.         }
  862.     }
  863.     return bBlend;
  864. }
  865. BOOL CBaseSurface::_RecursiveYUVBlend( Image* pImageOut,
  866.                                        HXxRect boundingRect,
  867.                                        CBaseSurface* pSurface,
  868.                                        INT32 lXOffset,
  869.                                        INT32 lYOffset)
  870. {
  871.     BOOL bRetVal = FALSE;
  872.     CHXMapPtrToPtr::Iterator i;
  873.     if( m_pSite->m_AlphaBlendNotifiers.GetCount()==0 )
  874.     {
  875.         return bRetVal;
  876.     }
  877.     for( i=m_pSite->m_AlphaBlendNotifiers.Begin() ;
  878.          i!=m_pSite->m_AlphaBlendNotifiers.End()  ;
  879.          ++i)
  880.     {
  881.         CHXBaseSite* pSite = (CHXBaseSite*)*i;
  882.         HXREGION* pReg = NULL;
  883.         //Find the region we need to blend with.
  884.         CHXMapPtrToPtr::Iterator j = pSite->m_AlphaBlendSites.Begin();
  885.         CHXBaseSite* pTmp = NULL;
  886.         while( j != pSite->m_AlphaBlendSites.End() && pTmp != m_pSite )
  887.         {
  888.             pTmp = (CHXBaseSite*)j.get_key();
  889.             if( pTmp == m_pSite )
  890.             {
  891.                 pReg = (HXREGION*)*j;
  892.                 break;
  893.             }
  894.             ++j;
  895.         }
  896.         //Hmmmm, something is probably wrong here...
  897.         if( HXEmptyRegion(pReg) )
  898.         {
  899.             HX_ASSERT("oops"==NULL);
  900.             break;
  901.         }
  902.         //Find the YUVA buffer we need to blend against....
  903.         Image* pImage = NULL;
  904.         j = pSite->m_pVideoSurface->m_YUVAImageList.Begin();
  905.         pTmp = NULL;
  906.         while( j!=pSite->m_pVideoSurface->m_YUVAImageList.End() )
  907.         {
  908.             pTmp = (CHXBaseSite*)j.get_key();
  909.             if( pTmp == m_pSite )
  910.             {
  911.                 pImage = (Image*)*j;
  912.                 break;
  913.             }
  914.             ++j;
  915.         }
  916.         //Now blend with this image....
  917.         if( pReg && pImage )
  918.         {
  919.             bRetVal = TRUE;
  920.             //blend by extents, blt by rects, and save for Blt().
  921.             for(int nIdx=0 ; nIdx<pReg->numRects ; nIdx++ )
  922.             {
  923.                 HXxRect BlockOut;
  924.                 BlockOut.left   = pReg->rects[nIdx].x1;
  925.                 BlockOut.top    = pReg->rects[nIdx].y1;
  926.                 BlockOut.right  = pReg->rects[nIdx].x2;
  927.                 BlockOut.bottom = pReg->rects[nIdx].y2;
  928.                 //Downscale all rects....
  929.                 double scaleX = 1;
  930.                 double scaleY = 1;
  931.                 scaleX = pSurface->m_scaleFactorX/pSite->m_pVideoSurface->m_scaleFactorX;
  932.                 scaleY = pSurface->m_scaleFactorY/pSite->m_pVideoSurface->m_scaleFactorY;
  933.                 //We must restrict this region to just the part that
  934.                 //overlaps the actuall YUV surface...
  935.                 int tlx = (int)((double)(m_pSite->m_topleft.x)/scaleX+.5);
  936.                 int tly = (int)((double)(m_pSite->m_topleft.y)/scaleY+.5);
  937.                 int xx = tlx - boundingRect.left;
  938.                 int yy = tly - boundingRect.top;
  939.                 if( (int)(BlockOut.left/scaleX+.5) < boundingRect.left )
  940.                     BlockOut.left = (INT32)(boundingRect.left*scaleX+.5);
  941.                 if( (int)(BlockOut.top/scaleY+.5) < boundingRect.top )
  942.                     BlockOut.top = (INT32)(boundingRect.top*scaleY+.5);
  943.                 if( (int)(BlockOut.right/scaleX+.5) > boundingRect.right )
  944.                     BlockOut.right = (INT32)(boundingRect.right*scaleX+.5);
  945.                 if( (int)(BlockOut.bottom/scaleY+.5) > boundingRect.bottom )
  946.                     BlockOut.bottom = (INT32)(boundingRect.bottom*scaleY+.5);
  947.                 BlockOut.left   =
  948.                     (int)((double)(BlockOut.left-m_pSite->m_topleft.x)/scaleX+.5);
  949.                 BlockOut.top    =
  950.                     (int)((double)(BlockOut.top-m_pSite->m_topleft.y)/scaleY+.5);
  951.                 BlockOut.right  =
  952.                     (int)((double)(BlockOut.right-m_pSite->m_topleft.x)/scaleX+.5);
  953.                 BlockOut.bottom =
  954.                     (int)((double)(BlockOut.bottom-m_pSite->m_topleft.y)/scaleY+.5);
  955.                 // Ensure we start on even pixels (for yuv blending/conversion)
  956.                 BlockOut.left &= ~1;
  957.                 BlockOut.top &= ~1;
  958.                 if( (BlockOut.right-BlockOut.left) & 1 )
  959.                 {
  960.                     BlockOut.right  &= ~1;
  961.                 }
  962.                 if( (BlockOut.bottom-BlockOut.top) & 1 )
  963.                 {
  964.                     BlockOut.bottom &= ~1;
  965.                 }
  966.                 int nSizeX = BlockOut.right-BlockOut.left;
  967.                 int nSizeY = BlockOut.bottom-BlockOut.top;
  968.                 //Take care of odd number lines and pels that are
  969.                 //not a multimple of four.
  970.                 int nSizeOutX = (nSizeX+3)&~3;
  971.                 int nSizeOutY = (nSizeY+1)&~1;
  972.                 int nPSiteRectLeft =
  973.                     (int)((double)(pReg->rects[nIdx].x1-pSite->m_topleft.x)/scaleX+.5);
  974.                 int nPSiteRectTop  =
  975.                     (int)((double)(pReg->rects[nIdx].y1-pSite->m_topleft.y)/scaleY+.5);
  976.                 //Now blend into the new buffer.
  977.                 //Have to pass pointers to the actual pixel.
  978.                 int nPImagePitch     = GETBITMAPPITCH(&pImage->bmiImage);
  979.                 int nPImageOutPitch  = GETBITMAPPITCH(&pImageOut->bmiImage);
  980.                 int nPImageDataPitch = nPImageOutPitch;
  981.                 if( BlockOut.left+xx < 0)
  982.                     xx = -BlockOut.left;
  983.                 if( BlockOut.top+yy < 0)
  984.                     yy = -BlockOut.top;
  985.                 if( BlockOut.left+xx+nSizeX > pImageOut->bmiImage.biWidth )
  986.                     xx -= 1;
  987.                 if( BlockOut.top+yy+nSizeY > pImageOut->bmiImage.biHeight )
  988.                     yy -= 1;
  989.                 zm_pColorAcc->I420andYUVA(
  990.                     //Botton YUV image
  991.                     pImageOut->pucImage,
  992.                     pImageOut->bmiImage.biWidth, pImageOut->bmiImage.biHeight,
  993.                     nPImageDataPitch,
  994.                     BlockOut.left+xx, BlockOut.top+yy,
  995.                     //Top source YUVA Image
  996.                     pImage->pucImage,
  997.                     pImage->bmiImage.biWidth, pImage->bmiImage.biHeight,
  998.                     nPImagePitch,
  999.                     nPSiteRectLeft, nPSiteRectTop,
  1000.                     //Output Image
  1001.                     pImageOut->pucImage,
  1002.                     pImageOut->bmiImage.biWidth, pImageOut->bmiImage.biHeight,
  1003.                     nPImageOutPitch,
  1004.                     BlockOut.left+xx, BlockOut.top+yy,
  1005.                     nSizeX, nSizeY,
  1006.                     // Output color format.
  1007.                     CID_I420
  1008.                     );
  1009.                 //Now keep drawing up the line through all
  1010.                 //overlapping ARGB images.
  1011.                 pSite->m_pVideoSurface->_RecursiveYUVBlend( pImageOut,
  1012.                                                             boundingRect,
  1013.                                                             pSurface,
  1014.                                                             lXOffset+xx,
  1015.                                                             lYOffset+yy
  1016.                                                             );
  1017.             }
  1018.         }
  1019.     }
  1020.     return bRetVal;
  1021. }
  1022. BOOL CBaseSurface::_SetUpBlendRects( HXBitmapInfoHeader* pBitmapInfo,
  1023.                                      UCHAR*               pImageData)
  1024. {
  1025.     BOOL bRetVal = FALSE;
  1026.     CHXMapPtrToPtr::Iterator i;
  1027.     //YUV optimized blending. We must blend 'up' the chain in this
  1028.     //case.  For each alpha notifier we have we must grab that sites
  1029.     //YUVA buffer and blend it against ourselves.
  1030.     CHXSimpleList::Iterator jj = m_imageBlocks.Begin();
  1031.     HXDestroyRegion(m_pAdditionalColorKey);
  1032.     m_pAdditionalColorKey = HXCreateRegion();
  1033.     if( m_pSite->m_AlphaBlendNotifiers.GetCount()==0 )
  1034.     {
  1035.         m_bYUVBlending = FALSE;
  1036.         return bRetVal;
  1037.     }
  1038.     for( i=m_pSite->m_AlphaBlendNotifiers.Begin() ;
  1039.          i!=m_pSite->m_AlphaBlendNotifiers.End()  ;
  1040.          ++i)
  1041.     {
  1042.         CHXBaseSite* pSite = (CHXBaseSite*)*i;
  1043.         HXREGION* pReg = NULL;
  1044.         //Find the region we need to blend with.
  1045.         CHXMapPtrToPtr::Iterator j = pSite->m_AlphaBlendSites.Begin();
  1046.         CHXBaseSite* pTmp = NULL;
  1047.         while( j != pSite->m_AlphaBlendSites.End() && pTmp != m_pSite )
  1048.         {
  1049.             pTmp = (CHXBaseSite*)j.get_key();
  1050.             if( pTmp == m_pSite )
  1051.             {
  1052.                 pReg = (HXREGION*)*j;
  1053.                 break;
  1054.             }
  1055.             ++j;
  1056.         }
  1057.         if( !pReg )
  1058.         {
  1059.             break;
  1060.         }
  1061.         //Find the YUVA buffer we need to blend against....
  1062.         Image* pImage = NULL;
  1063.         j = pSite->m_pVideoSurface->m_YUVAImageList.Begin();
  1064.         pTmp = NULL;
  1065.         while( j!=pSite->m_pVideoSurface->m_YUVAImageList.End() )
  1066.         {
  1067.             pTmp = (CHXBaseSite*)j.get_key();
  1068.             if( pTmp == m_pSite )
  1069.             {
  1070.                 pImage = (Image*)*j;
  1071.                 break;
  1072.             }
  1073.             ++j;
  1074.         }
  1075.         //Now blend with this image....
  1076.         if( pReg && pImage )
  1077.         {
  1078.             bRetVal = TRUE;
  1079.             //blend by extents, blt by rects, and save for Blt().
  1080.             for(int nIdx=0 ; nIdx<pReg->numRects ; nIdx++ )
  1081.             {
  1082.                 //reuse the last imageblock....
  1083.                 ImageBlock* pBlockOut = NULL;
  1084.                 Image* pImageOut      = NULL;
  1085.                 if( jj == m_imageBlocks.End() )
  1086.                 {
  1087.                     //We ran out of image blocks.
  1088.                     pBlockOut = new ImageBlock;
  1089.                     pImageOut = new Image;
  1090.                     memset( pImageOut, 0, sizeof(Image) );
  1091.                     memset( pBlockOut, 0, sizeof(ImageBlock) );
  1092.                     pBlockOut->pImage = pImageOut;
  1093.                     m_imageBlocks.AddTail((void*)pBlockOut);
  1094.                     jj = m_imageBlocks.End();
  1095.                 }
  1096.                 else
  1097.                 {
  1098.                     pBlockOut = (ImageBlock*)*jj;
  1099.                     ++jj;
  1100.                     pImageOut = pBlockOut->pImage;
  1101.                 }
  1102.                 pBlockOut->pSrcSite = pSite;
  1103.                 //Downscale all rects....
  1104.                 double scaleX = 1;
  1105.                 double scaleY = 1;
  1106.                 scaleX = m_scaleFactorX/pSite->m_pVideoSurface->m_scaleFactorX;
  1107.                 scaleY = m_scaleFactorY/pSite->m_pVideoSurface->m_scaleFactorY;
  1108.                 pBlockOut->rect.left   =
  1109.                     (int)((double)(pReg->rects[nIdx].x1-m_pSite->m_topleft.x)/scaleX+.5);
  1110.                 pBlockOut->rect.top    =
  1111.                     (int)((double)(pReg->rects[nIdx].y1-m_pSite->m_topleft.y)/scaleY+.5);
  1112.                 pBlockOut->rect.right  =
  1113.                     (int)((double)(pReg->rects[nIdx].x2-m_pSite->m_topleft.x)/scaleX+.5);
  1114.                 pBlockOut->rect.bottom =
  1115.                     (int)((double)(pReg->rects[nIdx].y2-m_pSite->m_topleft.y)/scaleY+.5);
  1116.                 // Ensure we start on even pixels (for yuv blending/conversion)
  1117.                 pBlockOut->rect.left &= ~1;
  1118.                 pBlockOut->rect.top &= ~1;
  1119.                 if( (pBlockOut->rect.right-pBlockOut->rect.left) & 1 )
  1120.                 {
  1121.                     pBlockOut->rect.right  &= ~1;
  1122.                 }
  1123.                 if( (pBlockOut->rect.bottom-pBlockOut->rect.top) & 1 )
  1124.                 {
  1125.                     pBlockOut->rect.bottom &= ~1;
  1126.                 }
  1127.                 int nSizeX = pBlockOut->rect.right-pBlockOut->rect.left;
  1128.                 int nSizeY = pBlockOut->rect.bottom-pBlockOut->rect.top;
  1129.                 //Take care of odd number lines and pels that are
  1130.                 //not a multimple of four.
  1131.                 int nSizeOutX = (nSizeX+3)&~3;
  1132.                 int nSizeOutY = (nSizeY+1)&~1;
  1133.                 int nPSiteRectLeft =
  1134.                     (int)((double)(pReg->rects[nIdx].x1-pSite->m_topleft.x)/scaleX+.5);
  1135.                 int nPSiteRectTop  =
  1136.                     (int)((double)(pReg->rects[nIdx].y1-pSite->m_topleft.y)/scaleY+.5);
  1137.                 pBlockOut->startX = nPSiteRectLeft;
  1138.                 pBlockOut->startY = nPSiteRectTop;
  1139. #ifdef _WIN32
  1140.                 int nResult = MakeBitmap( (LPBITMAPINFO)&(pImageOut->bmiImage),
  1141.                                           sizeof(pImageOut->bmiImage),
  1142.                                           CID_I420,
  1143.                                           nSizeOutX,
  1144.                                           nSizeOutY,
  1145.                                           NULL,
  1146.                                           0);
  1147. #else
  1148.                 int nResult = MakeBitmap( (HXBitmapInfo*)&(pImageOut->bmiImage),
  1149.                                           sizeof(pImageOut->bmiImage),
  1150.                                           CID_I420,
  1151.                                           nSizeOutX,
  1152.                                           nSizeOutY,
  1153.                                           NULL,
  1154.                                           0);
  1155. #endif
  1156.                 //Alloc it.
  1157.                 if( pImageOut->pucImage )
  1158.                 {
  1159.                     pImageOut->pucImage = (UCHAR*)
  1160.                         realloc( pImageOut->pucImage,
  1161.                                  sizeof(UCHAR)*pImageOut->bmiImage.biSizeImage
  1162.                                  );
  1163.                 }
  1164.                 else
  1165.                 {
  1166.                     pImageOut->pucImage = (UCHAR*)
  1167.                         malloc( sizeof(UCHAR)*pImageOut->bmiImage.biSizeImage);
  1168.                 }
  1169.                 if( pBitmapInfo && pImageData )
  1170.                 {
  1171.                     //Now blend into the new buffer.
  1172.                     //Have to pass pointers to the actual pixel.
  1173.                     int nPImageDataPitch = GETBITMAPPITCH(pBitmapInfo);
  1174.                     int nPImagePitch     = GETBITMAPPITCH(&pImage->bmiImage);
  1175.                     int nPImageOutPitch  = GETBITMAPPITCH(&pImageOut->bmiImage);
  1176.                     //Sanity check for rapid SetSize calls.
  1177.                     BOOL bDoIt =
  1178.                         nSizeX                 <= pImage->bmiImage.biWidth  &&
  1179.                         nSizeY                 <= pImage->bmiImage.biHeight &&
  1180.                         nSizeX                 <= pBitmapInfo->biWidth  &&
  1181.                         nSizeY                 <= pBitmapInfo->biHeight &&
  1182.                         pBlockOut->rect.right  <= pBitmapInfo->biWidth  &&
  1183.                         pBlockOut->rect.left   <= pBitmapInfo->biWidth  &&
  1184.                         pBlockOut->rect.bottom <= pBitmapInfo->biHeight &&
  1185.                         pBlockOut->rect.top    <= pBitmapInfo->biHeight &&
  1186.                         pBlockOut->rect.right  >=0 &&
  1187.                         pBlockOut->rect.left   >=0 &&
  1188.                         pBlockOut->rect.bottom >=0 &&
  1189.                         pBlockOut->rect.top    >=0 &&
  1190.                         nPSiteRectLeft         >= 0 &&
  1191.                         nPSiteRectTop          >= 0;
  1192.                     if( bDoIt )
  1193.                     {
  1194.                         zm_pColorAcc->I420andYUVA(
  1195.                             //Botton YUV image
  1196.                             pImageData,
  1197.                             pBitmapInfo->biWidth, pBitmapInfo->biHeight,
  1198.                             nPImageDataPitch,
  1199.                             pBlockOut->rect.left, pBlockOut->rect.top,
  1200.                             //Top source YUVA Image
  1201.                             pImage->pucImage,
  1202.                             pImage->bmiImage.biWidth, pImage->bmiImage.biHeight,
  1203.                             nPImagePitch,
  1204.                             nPSiteRectLeft, nPSiteRectTop,
  1205.                             //Output Image
  1206.                             pImageOut->pucImage,
  1207.                             pImageOut->bmiImage.biWidth, pImageOut->bmiImage.biHeight,
  1208.                             nPImageOutPitch,
  1209.                             0, 0,
  1210.                             nSizeX, nSizeY,
  1211.                             // Output color format.
  1212.                             CID_I420
  1213.                             );
  1214.                         //Now keep drawing up the line through all
  1215.                         //overlapping ARGB images.
  1216.                         pSite->m_pVideoSurface->_RecursiveYUVBlend( pImageOut,
  1217.                                                                     pBlockOut->rect,
  1218.                                                                     this, 0, 0);
  1219.                     }
  1220.                 }
  1221.             }
  1222.             if( m_imageBlocks.GetCount() )
  1223.             {
  1224.                 //Save the last time we did a blend on this site. This is used to
  1225.                 //help keep animated images blended over paused or stopped YUV
  1226.                 //content because on YUV we blend from the bottom up.
  1227.                 m_ulLastBlendTime = HX_GET_BETTERTICKCOUNT();
  1228.             }
  1229.             //Merge the region to m_Region for the YUV image.
  1230.             HXUnionRegion( m_pAdditionalColorKey, pReg, m_pAdditionalColorKey);
  1231.             //Remove the region from the overlapping ARGB surface
  1232.             //so it doesn't blt any more unless it changes.
  1233.             if( pSite && pSite->m_Region )
  1234.                 HXSubtractRegion( pSite->m_Region, pReg, pSite->m_Region );
  1235.         }
  1236.     }
  1237.     return bRetVal;
  1238. }
  1239. BOOL CBaseSurface::_AlphaSetupAndBlending(HXBitmapInfoHeader* pBitmapInfo,
  1240.                                           UCHAR*               pImageData,
  1241.                                           HXxRect&             rSrcRect,
  1242.                                           HXxRect&             rDestRect
  1243.                                           )
  1244. {
  1245.     BOOL  bDoAlpha = FALSE;
  1246.     CHXMapPtrToPtr::Iterator i;
  1247.     if (!pImageData)
  1248.         return bDoAlpha;
  1249.     //Are borders being drawn?
  1250.     INT32 nCID = GETBITMAPCOLOR(pBitmapInfo);
  1251.     HX_ASSERT( m_pSite );
  1252.     if( ( m_pucLastImage==NULL ||
  1253.           m_bmiLastImage.biWidth!=m_pSite->m_size.cx ||
  1254.           m_bmiLastImage.biHeight!=m_pSite->m_size.cy
  1255.           ) &&
  1256.         (( m_pSite->_BordersActive() ||
  1257.            m_pSite->_FadeTransitionActive()  ||
  1258.            m_pSite->_TakesPartInAlphaChain()) ||
  1259.          (( m_pSite->m_AlphaBlendNotifiers.GetCount() != 0 ||
  1260.             m_pSite->m_AlphaBlendSites.GetCount() != 0)
  1261.           &&
  1262.           !(IsYUV(nCID) && _IsDisplaySurfaceYuv())
  1263.           )
  1264.          ))
  1265.     {
  1266.         memset( &m_bmiLastImage, 0, sizeof( m_bmiLastImage ) );
  1267.         //Alloc new frame data...
  1268. #ifdef _WIN32
  1269.         int nResult = MakeBitmap( (LPBITMAPINFO)&m_bmiLastImage,
  1270.                                   sizeof(m_bmiLastImage),
  1271.                                   CID_ARGB32,
  1272.                                   m_pSite->m_size.cx,
  1273.                                   m_pSite->m_size.cy,
  1274.                                   NULL,
  1275.                                   0);
  1276. #else
  1277.         int nResult = MakeBitmap( (HXBitmapInfo*)&m_bmiLastImage,
  1278.                                   sizeof(m_bmiLastImage),
  1279.                                   CID_ARGB32,
  1280.                                   m_pSite->m_size.cx,
  1281.                                   m_pSite->m_size.cy,
  1282.                                   NULL,
  1283.                                   0);
  1284. #endif
  1285.         int size = sizeof(UCHAR)*m_bmiLastImage.biSizeImage;
  1286.         if( !m_pucLastImage )
  1287.             m_pucLastImage  = (UCHAR*)malloc(size);
  1288.         else
  1289.             m_pucLastImage  = (UCHAR*)realloc((void*)m_pucLastImage, size);
  1290.         HX_ASSERT( m_pucLastImage);
  1291.     }
  1292.     if( ( m_pucLastImage &&
  1293.           !m_pSite->_BordersActive() &&
  1294.           !m_pSite->_FadeTransitionActive()  &&
  1295.           !m_pSite->_TakesPartInAlphaChain() &&
  1296.           (
  1297.               m_pSite->m_AlphaBlendNotifiers.GetCount() == 0 &&
  1298.               m_pSite->m_AlphaBlendSites.GetCount() == 0 ||
  1299.               (IsYUV(nCID) && _IsDisplaySurfaceYuv())
  1300.               )
  1301.           )
  1302.         )
  1303.     {
  1304.         //We don't need the allocated buffer. Delete it.
  1305.         HX_FREE(m_pucLastImage);
  1306.     }
  1307.     //Save the image data. This is where all the alpha blending
  1308.     //will take place.
  1309.     if( m_pucLastImage &&
  1310.         ( m_pSite->m_AlphaBlendNotifiers.GetCount()!=0 ||
  1311.           CID_ARGB32==nCID ||
  1312.           m_pSite->_BordersActive() || m_pSite->_FadeTransitionActive()
  1313.           )
  1314.         )
  1315.     {
  1316.         //Stretch or shrink, if nessecary, to make the the image
  1317.         //the same size as our site. If we dont' we will get
  1318.         //alpha blending artifacts...
  1319. #ifdef _WINDOWS
  1320.         zm_pColorAcc->SetPlayer(m_pSite->m_pRootSurface->GetPlayer());
  1321. #endif
  1322.         BOOL bConverter = zm_pColorAcc->CheckColorConverter(nCID, CID_ARGB32);
  1323.         m_pSite->ColorConverterRequest(nCID, CID_ARGB32, bConverter);
  1324.         if (bConverter )
  1325.         {
  1326.             int cx = m_bmiLastImage.biWidth;
  1327.             int cy = m_bmiLastImage.biHeight;
  1328.             int pitchIn  = GETBITMAPPITCH( pBitmapInfo );
  1329.             int pitchOut = GETBITMAPPITCH( &m_bmiLastImage );
  1330.             zm_pColorAcc->ColorConvert(CID_ARGB32,
  1331.                                        m_pucLastImage,
  1332.                                        cx, cy,
  1333.                                        pitchOut,
  1334.                                        rDestRect.left,  rDestRect.top,
  1335.                                        rDestRect.right-rDestRect.left,
  1336.                                        rDestRect.bottom-rDestRect.top,
  1337.                                        nCID,
  1338.                                        pImageData,
  1339.                                        pBitmapInfo->biWidth,
  1340.                                        pBitmapInfo->biHeight,
  1341.                                        pitchIn,
  1342.                                        rSrcRect.left,  rSrcRect.top,
  1343.                                        rSrcRect.right-rSrcRect.left,
  1344.                                        rSrcRect.bottom-rSrcRect.top
  1345.                                        );
  1346.         }
  1347.         else
  1348.         {
  1349. #ifdef _DEBUG
  1350.             fprintf( stderr, "Can't get color converter!n" );
  1351. #endif
  1352.         }
  1353.         bDoAlpha=TRUE;
  1354.         //MOVE
  1355.         if( !IsYUV(nCID) )
  1356.             rSrcRect = rDestRect;
  1357.     }
  1358.     if(m_pSite->_BordersActive())
  1359.     {
  1360.         DrawTransitionBorders(&m_bmiLastImage,
  1361.                               m_pSite->m_nTransitionBorderWidth,
  1362.                               m_pSite->m_ulTransitionBorderColor,
  1363.                               m_pSite->m_bTransitionBlendBorder
  1364.                               );
  1365.         bDoAlpha = TRUE;
  1366.     }
  1367.     //Do we even care about alpha blening ourselves?
  1368.     if( ( nCID==CID_ARGB32 ||
  1369.           m_pSite->_BlendedBordersActive() ||
  1370.           m_pSite->_FadeTransitionActive() ) &&
  1371.         m_pSite->GetParentSite() )
  1372.     {
  1373.         //Alphablend against all of our regions.
  1374.         for( i=m_pSite->m_AlphaBlendSites.Begin() ;
  1375.              i!=m_pSite->m_AlphaBlendSites.End()  ;
  1376.              ++i)
  1377.         {
  1378.             CHXBaseSite* pSite = (CHXBaseSite*) i.get_key();
  1379.             HXREGION* pRegion = (HXREGION*)*i;
  1380.             //We need to intersect this region with the rect that we
  1381.             //are actually blt'ing. SubRect support.
  1382.             HXxRect TmpRect = rDestRect;
  1383.             TmpRect.left   += m_pSite->m_topleft.x;
  1384.             TmpRect.right  += m_pSite->m_topleft.x;
  1385.             TmpRect.top    += m_pSite->m_topleft.y;
  1386.             TmpRect.bottom += m_pSite->m_topleft.y;
  1387.             HXREGION* pInter  = HXCreateRectRegion( TmpRect.left,
  1388.                                                     TmpRect.top,
  1389.                                                     TmpRect.right-TmpRect.left,
  1390.                                                     TmpRect.bottom-TmpRect.top
  1391.                                                     );
  1392.             HXIntersectRegion( pInter, pRegion, pInter );
  1393.             CBaseSurface* pTmp = pSite->m_pVideoSurface;
  1394.             if( pTmp->m_pucLastImage &&
  1395.                 !(IsYUV(GETBITMAPCOLOR(&pTmp->m_bmiLastImage)) && pTmp->_IsDisplaySurfaceYuv())
  1396.                 )
  1397.             {
  1398.                 _AlphaBlend( pInter,
  1399.                              pSite->m_pVideoSurface->m_pucLastImage,
  1400.                              &(pSite->m_pVideoSurface->m_bmiLastImage),
  1401.                              &(pSite->m_topleft),
  1402.                              m_pucLastImage,
  1403.                              &m_bmiLastImage,
  1404.                              &(m_pSite->m_topleft)
  1405.                              );
  1406.             }
  1407.             HXDestroyRegion( pInter );
  1408.         }
  1409.         bDoAlpha = TRUE;
  1410.     }
  1411.     //For optimized YUV alphablending.  Create a YUVA image here, if
  1412.     //we have a YUV site that we blend against, and then down-scale
  1413.     //and color convert to YUVA. The YUV render's call to Blt() will
  1414.     //grab this and alphablend against us.
  1415.     //Clean up the old ones..
  1416.     i = m_YUVAImageList.Begin();
  1417.     while(i != m_YUVAImageList.End())
  1418.     {
  1419.         Image* pImage = (Image*)*i;
  1420.         HX_DELETE(pImage->pucImage);
  1421.         HX_DELETE(pImage);
  1422.         ++i;
  1423.     }
  1424.     m_YUVAImageList.RemoveAll();
  1425.     BOOL bHaveYUVBlender = FALSE;
  1426.     for( i=m_pSite->m_AlphaBlendSites.Begin() ;
  1427.          i!=m_pSite->m_AlphaBlendSites.End() ;
  1428.          ++i)
  1429.     {
  1430.         //CHXBaseSite* pSite = (CHXBaseSite*) i.get_key();
  1431.         CHXBaseSite* pSite = NULL;
  1432.         //Do a recursive search for YUV surfaces below us.
  1433.         CHXBaseSite* pSiteOrig = (CHXBaseSite*)i.get_key();
  1434.         pSite = _SearchForYUV( pSiteOrig );
  1435.         if( pSite && pSite->m_pVideoSurface )
  1436.         {
  1437.             int nCID2 = GETBITMAPCOLOR(&(pSite->m_pVideoSurface->m_bmiLastBlt));
  1438.             if( IsYUV(nCID2) && pSite->m_pVideoSurface->_IsDisplaySurfaceYuv())
  1439.             {
  1440.                 //Create a YUVA buffer to hold the last frame.
  1441.                 Image* pImage = new Image;
  1442.                 memset( pImage, 0, sizeof( Image) );
  1443.                 //Color convert to scaled YUVA into image struct.
  1444.                 double scaleX = pSite->m_pVideoSurface->m_scaleFactorX/m_scaleFactorX;
  1445.                 double scaleY = pSite->m_pVideoSurface->m_scaleFactorY/m_scaleFactorY;
  1446.                 int nSizeX = (int)(((double)(m_bmiLastImage.biWidth))/scaleX+.5);
  1447.                 int nSizeY = (int)(((double)(m_bmiLastImage.biHeight))/scaleY+.5);
  1448.                 //Fix non mod quad sizes
  1449.                 nSizeX = (nSizeX+3)&~3;
  1450.                 nSizeY = (nSizeY+1)&~1;
  1451.                 UCHAR*              pucDownscaledRGB = NULL;
  1452.                 HXBitmapInfoHeader bmiDownscaledRGB;
  1453.                 memset( &bmiDownscaledRGB, 0, sizeof( bmiDownscaledRGB ) );
  1454. #ifdef _WIN32
  1455.                 MakeBitmap( (LPBITMAPINFO)&(pImage->bmiImage),
  1456.                             sizeof(pImage->bmiImage),
  1457.                             CID_YUVA,
  1458.                             nSizeX,
  1459.                             nSizeY,
  1460.                             NULL,
  1461.                             0);
  1462.                 MakeBitmap( (LPBITMAPINFO)&bmiDownscaledRGB,
  1463.                             sizeof(bmiDownscaledRGB),
  1464.                             CID_ARGB32,
  1465.                             nSizeX,
  1466.                             nSizeY,
  1467.                             NULL,
  1468.                             0);
  1469. #else
  1470.                 MakeBitmap( (HXBitmapInfo*)&(pImage->bmiImage),
  1471.                             sizeof(pImage->bmiImage),
  1472.                             CID_YUVA,
  1473.                             nSizeX,
  1474.                             nSizeY,
  1475.                             NULL,
  1476.                             0);
  1477.                 MakeBitmap( (HXBitmapInfo*)&bmiDownscaledRGB,
  1478.                             sizeof(bmiDownscaledRGB),
  1479.                             CID_ARGB32,
  1480.                             nSizeX,
  1481.                             nSizeY,
  1482.                             NULL,
  1483.                             0);
  1484. #endif
  1485.                 //Alloc it.
  1486.                 pImage->pucImage = new UCHAR[pImage->bmiImage.biSizeImage];
  1487.                 pucDownscaledRGB = new UCHAR[bmiDownscaledRGB.biSizeImage];
  1488.                 //downscale the ARGB first....
  1489.                 int ik = 0;
  1490.                 UCHAR*               pBits = pImageData;
  1491.                 HXBitmapInfoHeader* pBIS  = pBitmapInfo;
  1492.                 if( IsYUV(nCID) && bDoAlpha )
  1493.                 {
  1494.                     pBits = m_pucLastImage;
  1495.                     pBIS  = &m_bmiLastImage;
  1496.                 }
  1497.                 BOOL bConverter = zm_pColorAcc->CheckColorConverter(CID_ARGB32, CID_ARGB32);
  1498.                 pSite->ColorConverterRequest(CID_ARGB32, CID_ARGB32, bConverter);
  1499.                 if (bConverter)
  1500.                 {
  1501.                     ik = zm_pColorAcc->ColorConvert(
  1502.                         CID_ARGB32,
  1503.                         pucDownscaledRGB,
  1504.                         bmiDownscaledRGB.biWidth,
  1505.                         bmiDownscaledRGB.biHeight,
  1506.                         GETBITMAPPITCH(&bmiDownscaledRGB),
  1507.                         0,
  1508.                         0,
  1509.                         nSizeX,
  1510.                         nSizeY,
  1511.                         CID_ARGB32,
  1512.                         pBits,
  1513.                         pBIS->biWidth,
  1514.                         pBIS->biHeight,
  1515.                         GETBITMAPPITCH(pBIS),
  1516.                         0,
  1517.                         0,
  1518.                         pBitmapInfo->biWidth,
  1519.                         pBitmapInfo->biHeight
  1520.                         );
  1521.                 }
  1522.                 HX_ASSERT(ik==0);
  1523.                 //We must apply any fade transitions here......
  1524.                 BOOL  bFade=FALSE;
  1525.                 int   completeness = 0;
  1526.                 if( (m_pSite->m_fpTransitionEffect == Crossfade ||
  1527.                      m_pSite->m_fpTransitionEffect == FadeToColor ||
  1528.                      m_pSite->m_fpTransitionEffect == FadeFromColor )
  1529.                     && m_pSite->m_nTransitionState!=1000 )
  1530.                 {
  1531.                     completeness = m_pSite->m_nTransitionState;
  1532.                     if(m_pSite->m_bTransitionReversed)
  1533.                     {
  1534.                         completeness = 1000 - completeness;
  1535.                     }
  1536.                     if( m_pSite->m_fpTransitionEffect== FadeFromColor)
  1537.                     {
  1538.                         completeness = 1000 - completeness;
  1539.                     }
  1540.                     //Map [0,1000] --> [0,1024] for fixed point fade math.
  1541.                     completeness = (int)((float)completeness*1024.0/1000.0);
  1542.                     bFade=TRUE;
  1543.                     if( bFade )
  1544.                     {
  1545.                         int alpha     = 0;
  1546.                         int alphasave = 0;
  1547.                         ULONG32* pTmp = (ULONG32*)pucDownscaledRGB;
  1548.                         for( UINT32 i=0 ; i< bmiDownscaledRGB.biSizeImage/4; i++, pTmp++ )
  1549.                         {
  1550.                             if( m_pSite->m_fpTransitionEffect == Crossfade )
  1551.                             {
  1552.                                 //fixed point version of (comp/1000 * alpha )
  1553.                                 alpha = (*pTmp & 0xff000000)>>24;
  1554.                                 alpha = ((completeness*(255-alpha)+512))>>10;
  1555.                                 alphasave = (255-alpha)<<24;
  1556.                                 *pTmp = (*pTmp&0x00ffffff) | alphasave;
  1557.                             }
  1558.                             else if( m_pSite->m_fpTransitionEffect == FadeToColor ||
  1559.                                      m_pSite->m_fpTransitionEffect == FadeFromColor)
  1560.                             {
  1561.                                 //Not only affect alpha but also fading to color.
  1562.                                 alpha = (completeness*255+512)>>10;
  1563.                                 UINT32 fadeColor = (m_pSite->m_ulTransitionFadeColor&0x00ffffff)|(alpha<<24);
  1564.                                 int pTmpAlpha = (*pTmp&0xff000000)>>24;
  1565.                                 int newalpha = (((0xff-alpha)*pTmpAlpha)>>8)<<24;
  1566.                                 *pTmp = newalpha |
  1567.                                     (((alpha*( (fadeColor&0x00ff0000)-(*pTmp&0x00ff0000))+((*pTmp&0x00ff0000)<<8))>>8)&0x00ff0000)|
  1568.                                     (((alpha*( (fadeColor&0x0000ff00)-(*pTmp&0x0000ff00))+((*pTmp&0x0000ff00)<<8))>>8)&0x0000ff00)|
  1569.                                     (((alpha*( (fadeColor&0x000000ff)-(*pTmp&0x000000ff))+((*pTmp&0x000000ff)<<8))>>8)&0x000000ff);
  1570.                             }
  1571.                         }
  1572.                     }
  1573.                 }
  1574.                 //Color convert downscaled ARGB to YUVA
  1575.                 bConverter = zm_pColorAcc->CheckColorConverter(CID_ARGB32, CID_YUVA);
  1576.                 pSite->ColorConverterRequest(CID_ARGB32, CID_YUVA, bConverter);
  1577.                 if( bConverter )
  1578.                     ik = zm_pColorAcc->ColorConvert(
  1579.                         CID_YUVA,
  1580.                         pImage->pucImage,
  1581.                         pImage->bmiImage.biWidth,
  1582.                         pImage->bmiImage.biHeight,
  1583.                         GETBITMAPPITCH(&pImage->bmiImage),
  1584.                         0,
  1585.                         0,
  1586.                         nSizeX,
  1587.                         nSizeY,
  1588.                         CID_ARGB32,
  1589.                         pucDownscaledRGB,
  1590.                         bmiDownscaledRGB.biWidth,
  1591.                         bmiDownscaledRGB.biHeight,
  1592.                         GETBITMAPPITCH(&bmiDownscaledRGB),
  1593.                         0,
  1594.                         0,
  1595.                         bmiDownscaledRGB.biWidth,
  1596.                         bmiDownscaledRGB.biHeight
  1597.                         );
  1598.                 HX_ASSERT( ik==0 );
  1599.                 HX_VECTOR_DELETE( pucDownscaledRGB );
  1600.                 //Add into YUVA image map for this site.
  1601.                 m_pSite->_TLSLock();
  1602.                 m_YUVAImageList.SetAt( pSiteOrig, pImage );
  1603.                 pSiteOrig->m_pVideoSurface->m_bYUVBlending = TRUE;
  1604.                 m_pSite->_TLSUnlock();
  1605.                 //Remove the region from the overlapping ARGB surface
  1606.                 //so it doesn't blt any more unless it changes.
  1607.                 HXREGION* pRegion = (HXREGION*)*i;
  1608.                 //Wow, recursive YUV blending is not fun. If we are on
  1609.                 //top of an ARGB image and it is on top of a YUV image
  1610.                 //then we need subtract only that part of our region
  1611.                 //that overlaps the ARGB image *AND* the YUV image
  1612.                 //down below.
  1613.                 HXREGION*   hTemp  = NULL;
  1614.                 HXxSize   size;
  1615.                 HXxPoint* pPosition = NULL;
  1616.                 pSite->GetSize( size );
  1617.                 pPosition = pSite->GetOrigin();
  1618.                 hTemp = pSite->Transition(pPosition->x, pPosition->y,
  1619.                                           pPosition->x + size.cx,
  1620.                                           pPosition->y + size.cy);
  1621.                 HXIntersectRegion( hTemp, pRegion, hTemp );
  1622.                 HXSubtractRegion( m_pSite->m_Region, hTemp, m_pSite->m_Region );
  1623.                 HXDestroyRegion( hTemp );
  1624.             }
  1625.         }
  1626.     }
  1627.     //-----------------------------------------
  1628.     // YUV Blending Part 2
  1629.     //-----------------------------------------
  1630.     if( IsYUV(nCID)&& _IsDisplaySurfaceYuv() &&
  1631.         m_pSite->m_AlphaBlendNotifiers.GetCount() )
  1632.     {
  1633.         _SetUpBlendRects(pBitmapInfo, pImageData);
  1634.     }
  1635. #if defined(_DEBUG) && 0
  1636.     if( IsYUV(nCID) && ((m_nBltMode==HX_OVERLAY_BLT&&!m_bOffBecauseofShinking)  || m_pLinkedOverlay) )
  1637.     {
  1638.         char szBuff[256]; /* Flawfinder: ignore */
  1639.         sprintf( szBuff, "Left with m_imageBlocks: %dn", m_imageBlocks.GetCount() ); /* Flawfinder: ignore */
  1640.         _DumpString(szBuff);
  1641.         CHXSimpleList::Iterator jjj = m_imageBlocks.Begin();
  1642.         while(jjj != m_imageBlocks.End())
  1643.         {
  1644.             ImageBlock* pBlock = (ImageBlock*)*jjj;
  1645.             sprintf( szBuff, "   Block: (%d, %d) -- (%d, %d)n", /* Flawfinder: ignore */
  1646.                      pBlock->rect.left,
  1647.                      pBlock->rect.top,
  1648.                      pBlock->rect.right,
  1649.                      pBlock->rect.bottom
  1650.                      );
  1651.             _DumpString(szBuff);
  1652.             ++jjj;
  1653.         }
  1654.     }
  1655. #endif
  1656.     return bDoAlpha;
  1657. }
  1658. void CBaseSurface::_ConstructRects(HXxRect&   rSrcRectCopy,
  1659.                                    HXxRect&   rDestRectCopy,
  1660.                                    BOOL       bDoAlpha,
  1661.                                    int&       nNumRects,
  1662.                                    HXxRect**  paSrcRects,
  1663.                                    HXxRect**  paDestRects,
  1664.                                    HXREGION* pAdditionalRegion
  1665.                                    )
  1666. {
  1667.     HXxRect  newDestRect;
  1668.     HXxRect  origDestRect = rDestRectCopy;
  1669.     HXxPoint originOffset;
  1670.     memcpy(&originOffset,m_pSite->GetOrigin(),sizeof(HXxPoint)); /* Flawfinder: ignore */
  1671.     rDestRectCopy.left      = (INT32) ((double) rDestRectCopy.left   *
  1672.                                        m_fScrollBarZoom + 0.5);
  1673.     rDestRectCopy.right     = (INT32) ((double) rDestRectCopy.right  *
  1674.                                        m_fScrollBarZoom + 0.5);
  1675.     rDestRectCopy.top       = (INT32) ((double) rDestRectCopy.top    *
  1676.                                        m_fScrollBarZoom + 0.5);
  1677.     rDestRectCopy.bottom    = (INT32) ((double) rDestRectCopy.bottom *
  1678.                                        m_fScrollBarZoom + 0.5);
  1679.     newDestRect.left    = rDestRectCopy.left   + originOffset.x;
  1680.     newDestRect.right   = rDestRectCopy.right  + originOffset.x;
  1681.     newDestRect.top     = rDestRectCopy.top    + originOffset.y;
  1682.     newDestRect.bottom  = rDestRectCopy.bottom + originOffset.y;
  1683.     //If we are in full screen we have to offset our origin
  1684.     HXxPoint screenOffset = m_pSite->GetScreenOffset();
  1685.     //compute our scaling factor if we don't have access to the real
  1686.     //site scaling info via BltSubRects or IHXOriginalSize.
  1687.     if( !m_pSite->SiteScaleingInfoAvailable() || m_pSite->_TakesPartInAlphaChain()  )
  1688.     {
  1689.         int nDestDX = rDestRectCopy.right  - rDestRectCopy.left;
  1690.         int nSrcDX  = rSrcRectCopy.right   - rSrcRectCopy.left;
  1691.         int nDestDY = rDestRectCopy.bottom - rDestRectCopy.top;
  1692.         int nSrcDY  = rSrcRectCopy.bottom  - rSrcRectCopy.top;
  1693.         m_scaleFactorX = (double)nDestDX/(double)nSrcDX;
  1694.         m_scaleFactorY = (double)nDestDY/(double)nSrcDY;
  1695.     }
  1696.     //Scrolling support. XXXAH phew. We might want to go over this!
  1697.     IHXValues* pValues = NULL;
  1698.     ULONG32     bScroll = FALSE;
  1699.     HXxRect     rect;
  1700.     int xSrcOffSet = 0;
  1701.     int ySrcOffSet = 0;
  1702.     if( m_pSite->QueryInterface( IID_IHXValues, (void**) &pValues )==HXR_OK )
  1703.     {
  1704.         pValues->GetPropertyULONG32("ScrollingSite", bScroll);
  1705.         if (bScroll)
  1706.         {
  1707.             m_pSite->GetWindowRect(&rect);
  1708.             HXxSize size;
  1709.             size.cx = rect.right - rect.left;
  1710.             size.cy = rect.bottom - rect.top;
  1711.             if (rDestRectCopy.right - rDestRectCopy.left > size.cx)
  1712.             {
  1713.                 int xDelta = rDestRectCopy.right - rDestRectCopy.left - 1;
  1714.                 m_pSite->SafeSetXSliderRange(xDelta);
  1715.                 int xsliderPos      = m_pSite->GetXSliderPos();
  1716.                 int currentXDelta   = m_pSite->GetXSliderRange();
  1717.                 // find the thumb size
  1718.                 HXxSize parentSize;
  1719.                 m_pSite->m_pParentSite->GetSize(parentSize);
  1720.                 xDelta = xDelta - parentSize.cx + m_pSite->GetSliderWidth();
  1721.                 currentXDelta -=parentSize.cx;
  1722.                 if(xsliderPos && currentXDelta)
  1723.                 {
  1724.                     double sliderPercentage = (double)xsliderPos / currentXDelta;
  1725.                     if (sliderPercentage > 1.0) sliderPercentage = 1.0; // how does this happen?
  1726.                     xSrcOffSet = (int) ((sliderPercentage * xDelta ) / m_scaleFactorX + 0.5) ;
  1727.                 }
  1728.                 //Modify the dest rect. This is a bit crazy.
  1729.                 newDestRect.left    = originOffset.x;
  1730.                 newDestRect.right   = originOffset.x + size.cx - m_pSite->GetSliderWidth();
  1731.             }
  1732.             if (rDestRectCopy.bottom - rDestRectCopy.top > size.cy)
  1733.             {
  1734.                 int yDelta = rDestRectCopy.bottom - rDestRectCopy.top - 1;
  1735.                 m_pSite->SafeSetYSliderRange(yDelta);
  1736.                 int ysliderPos      = m_pSite->GetYSliderPos();
  1737.                 int currentYDelta   = m_pSite->GetYSliderRange();
  1738.                 // find the thumb size
  1739.                 HXxSize parentSize;
  1740.                 m_pSite->m_pParentSite->GetSize(parentSize);
  1741.                 yDelta = yDelta - parentSize.cy + m_pSite->GetSliderHeight();
  1742.                 currentYDelta -=parentSize.cy;
  1743.                 if(ysliderPos && currentYDelta)
  1744.                 {
  1745.                     double sliderPercentage = (double)ysliderPos / currentYDelta;
  1746.                     if (sliderPercentage > 1.0) sliderPercentage = 1.0; // how does this happen?
  1747.                     ySrcOffSet = (int) ((sliderPercentage * yDelta ) / m_scaleFactorY + 0.5) ;
  1748.                 }
  1749.                 //Modify the dest rect. This is a bit crazy.
  1750.                 newDestRect.top     = originOffset.y;
  1751.                 newDestRect.bottom  = originOffset.y + size.cy - m_pSite->GetSliderHeight();
  1752.             }
  1753.         }
  1754.         HX_RELEASE(pValues);
  1755.     }
  1756.     rDestRectCopy = newDestRect;
  1757.     CBaseRootSurface* pRootSurface = m_pSite->GetRootSurface();
  1758.     HX_ASSERT( pRootSurface );
  1759.     if( !pRootSurface )
  1760.         return;
  1761.     nNumRects = 0;
  1762.     if( !m_pSite->m_Region )
  1763.         return;
  1764.     HXREGION* pWhole = HXCreateRegion();
  1765.     if( pAdditionalRegion)
  1766.     {
  1767.         HXUnionRegion( m_pSite->m_Region, pAdditionalRegion, pWhole );
  1768.     }
  1769.     else
  1770.     {
  1771.         HXUnionRegion( m_pSite->m_Region, pWhole, pWhole );
  1772.     }
  1773.     //Intersect incoming rectangle with our region.
  1774.     HXREGION* pDirty = HXCreateRectRegion( newDestRect.left,
  1775.                                            newDestRect.top,
  1776.                                            newDestRect.right-newDestRect.left,
  1777.                                            newDestRect.bottom-newDestRect.top
  1778.                                            );
  1779.     if( pDirty )
  1780.     {
  1781.         HXIntersectRegion( pDirty, pWhole, pWhole );
  1782.         HXDestroyRegion( pDirty );
  1783.     }
  1784.     HX_ASSERT( pWhole );
  1785.     //Set up the array of src and dest rect returns
  1786.     if ((_IsDisplaySurfaceYuv() && HX_OVERLAY_BLT == m_nBltMode) &&
  1787.         (m_bVideoSurface2 || !m_bYUVBlending) &&
  1788.         !m_pLinkedOverlay && !m_LinkedSites.GetCount()
  1789.         )
  1790.         nNumRects = 1;
  1791.     else
  1792.         nNumRects = pWhole->numRects;
  1793.     if( NULL == paSrcRects )
  1794.         *paSrcRects  = (HXxRect*)malloc(sizeof(HXxRect)*nNumRects);
  1795.     else
  1796.     {
  1797. #ifdef _DEBUG
  1798.         // We can not trace reallocs in pndebug...so use allocs when tracing
  1799.         if (m_bAllocHook)
  1800.         {
  1801.             free(*paSrcRects);
  1802.             *paSrcRects  = (HXxRect*)malloc(sizeof(HXxRect)*nNumRects);
  1803.         }
  1804.         else
  1805.             *paSrcRects  = (HXxRect*)realloc(*paSrcRects, sizeof(HXxRect)*nNumRects);
  1806. #else
  1807.         *paSrcRects  = (HXxRect*)realloc(*paSrcRects, sizeof(HXxRect)*nNumRects);
  1808. #endif
  1809.     }
  1810.     if( NULL == paDestRects )
  1811.         *paDestRects  = (HXxRect*)malloc(sizeof(HXxRect)*nNumRects);
  1812.     else
  1813.     {
  1814. #ifdef _DEBUG
  1815.         // We can not trace reallocs in pndebug...so use allocs when tracing
  1816.         if (m_bAllocHook)
  1817.         {
  1818.             free(*paDestRects);
  1819.             *paDestRects  = (HXxRect*)malloc(sizeof(HXxRect)*nNumRects);
  1820.         }
  1821.         else
  1822.             *paDestRects  = (HXxRect*)realloc(*paDestRects, sizeof(HXxRect)*nNumRects);
  1823. #else
  1824.         *paDestRects  = (HXxRect*)realloc(*paDestRects, sizeof(HXxRect)*nNumRects);
  1825. #endif
  1826.     }
  1827.     HX_ASSERT( paSrcRects );
  1828.     HX_ASSERT( paDestRects );
  1829.     for( int i=0 ; i<nNumRects ; i++)
  1830.     {
  1831.         HXxRect rgnRect;
  1832.         rgnRect.left     = pWhole->rects[i].x1;
  1833.         rgnRect.top      = pWhole->rects[i].y1;
  1834.         rgnRect.right    = pWhole->rects[i].x2;
  1835.         rgnRect.bottom   = pWhole->rects[i].y2;
  1836.         if( (_IsDisplaySurfaceYuv() && HX_OVERLAY_BLT == m_nBltMode) &&
  1837.             (m_bVideoSurface2 || !m_bYUVBlending ) &&
  1838.             !m_pLinkedOverlay && !m_LinkedSites.GetCount()
  1839.             )
  1840.         {
  1841.             //Merge our region with the list of regions in the image block
  1842.             //list....
  1843.             HXREGION* pRegTmp = HXCreateRegion();
  1844.             HXUnionRegion( pRegTmp, pWhole, pRegTmp );
  1845.             CHXMapPtrToPtr::Iterator i;
  1846.             for( i=m_pSite->m_AlphaBlendNotifiers.Begin() ;
  1847.                  i!=m_pSite->m_AlphaBlendNotifiers.End()  ;
  1848.                  ++i)
  1849.             {
  1850.                 CHXBaseSite* pSite = (CHXBaseSite*)*i;
  1851.                 HXREGION* pReg = NULL;
  1852.                 //Find the region we need to blend with.
  1853.                 CHXMapPtrToPtr::Iterator j = pSite->m_AlphaBlendSites.Begin();
  1854.                 CHXBaseSite* pTmp = NULL;
  1855.                 while( j != pSite->m_AlphaBlendSites.End() && pTmp != m_pSite )
  1856.                 {
  1857.                     pTmp = (CHXBaseSite*)j.get_key();
  1858.                     if( pTmp == m_pSite )
  1859.                     {
  1860.                         pReg = (HXREGION*)*j;
  1861.                         HXUnionRegion( pRegTmp, pReg, pRegTmp );
  1862.                         break;
  1863.                     }
  1864.                     ++j;
  1865.                 }
  1866.             }
  1867.             //now just take the extents.....
  1868.             rgnRect.left     = pRegTmp->extents.x1;
  1869.             rgnRect.top      = pRegTmp->extents.y1;
  1870.             rgnRect.right    = pRegTmp->extents.x2;
  1871.             rgnRect.bottom   = pRegTmp->extents.y2;
  1872.             HXDestroyRegion( pRegTmp );
  1873.         }
  1874.         UINT32 whichMonitor;
  1875.         for (whichMonitor = 0; whichMonitor < pRootSurface->_GetNumberOfMonitors(); whichMonitor++)
  1876.         {