basesurf.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:145k
源码类别:

Symbian

开发平台:

C/C++

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