macsurf.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,064 行 · 第 1/3 页

CPP
1,064
字号
	//    desktop area.
	//
	// But if we ensure that after the first successful blit we
	// then rebuild the overlay, we never encounter the problem
	// in the sequence of events. I need to revisit this!
	// I created a stand-alone app that tried to repro the problem
	// and I couldn't. I added window sizing code to CarbMini and
	// couldn't repro the problem. I don't know if we're getting
	// called when we're in a bad state in the middle of resizing
	// or what.
	//
	// The whole notion of the image sequence technique is that when
	// you know that your grafport is going to be consistent for awhile
	// you can take advantage of that by using a sequence ID so each
	// blit can rely on the parameters that remain consistent. What this
	// workaround is doing is probably that something in the
	// grafport has changed and we haven't detected it. What I don't
	// know, but I should look into the sequence of events of first
	// overlay rebuild, actual SizeWindow() command, second overlay blit
	// that would slam to the desktop if we didn't kludge.
	//
	// Initially I thought that there were two possible kludges that
	// would avoid the problem. One was to delay the Carbon Timer by
	// a millisecond. The other was to use this "catch up" technique.
	// It turns out that when I delayed the Carbon Timer, I was able
	// to reproduce the problem by actively resizing the simple case,
	// and most of the time using a more complex SMIL repro case.
	// The "catch up" technique used to have a simple boolean for
	// whether the kludge should kick in. Now it has a counter that's
	// higher for more complicated SMIL presentations. I don't know
	// what the magic number is, but using a boolean (i.e. "one")
	// was too low in complex SMIL presentations, and the number of
	// sites seems to work.
	//
	// xxxbobclark 20 Sep 02
	
	static ULONG32 sbCatchUp = 0;
	
	RgnHandle newMaskRgn = nil;
	
	if (bOverlayRebuildingRequired)
	{
	    CHXMacSite* pSite = (CHXMacSite*)zm_pOverlaySurface->m_pSite;

	    HXREGION* pEntireReg = HXCreateRegion();
	    HXUnionRegion(pEntireReg, pSite->m_Region, pEntireReg);

	    // xxxbobclark do this "manual clipping" thing to ensure that opaque
	    // parents are clipped out.
	    CHXMacSite* parentSite = (CHXMacSite*)pSite->GetParentSite();
	    while (parentSite)
	    {
		HXIntersectRegion(pEntireReg, parentSite->m_RegionWithoutChildren, pEntireReg);
		parentSite = (CHXMacSite*)parentSite->GetParentSite();
	    }
		
	    // xxxbobclark chunk of code snagged from CBaseSurface::FillColorKey.
	    // Necessary because our overlay clip region needs to be able to
	    // differentiate between clipped-out areas and alpha-blended areas.
	    CHXMapPtrToPtr::Iterator ii;
	    for( ii=pSite->m_AlphaBlendNotifiers.Begin() ;
			 ii!=pSite->m_AlphaBlendNotifiers.End()  ;
			 ++ii)
	    {
		CHXBaseSite* pPotentialAlphaBlendedSite = (CHXBaseSite*)*ii;
		HXREGION* pReg = NULL;
		CHXMapPtrToPtr::Iterator j = pPotentialAlphaBlendedSite->m_AlphaBlendSites.Begin();
		CHXBaseSite* pTmpSite = NULL;
		while( j != pPotentialAlphaBlendedSite->m_AlphaBlendSites.End() && pTmpSite != pSite )
		{
		    pTmpSite = (CHXBaseSite*)j.get_key();
		    if( pTmpSite == pSite )
		    {
			pReg = (HXREGION*)*j;
			HXUnionRegion( pEntireReg, pReg, pEntireReg );
			break;
		    }
		    ++j;
		}
	    }

	    // xxxbobclark is this involved in a linked overlay?
	    // If so, we need to include the linked site's regions.

	    CHXSimpleList::Iterator linkedSitesIter;

	    for (	linkedSitesIter = m_LinkedSites.Begin();
			linkedSitesIter != m_LinkedSites.End();
			++linkedSitesIter)
	    {
		CHXBaseSite* pSite = (CHXBaseSite*)(*linkedSitesIter);
		HXUnionRegion(pEntireReg, pSite->m_Region, pEntireReg);

		CHXMapPtrToPtr::Iterator ii;
		for( ii=pSite->m_AlphaBlendNotifiers.Begin() ;
				ii!=pSite->m_AlphaBlendNotifiers.End()  ;
				++ii)
		{
		    CHXBaseSite* pPotentialAlphaBlendedSite = (CHXBaseSite*)*ii;
		    HXREGION* pReg = NULL;
		    CHXMapPtrToPtr::Iterator j = pPotentialAlphaBlendedSite->m_AlphaBlendSites.Begin();
		    CHXBaseSite* pTmpSite = NULL;
		    while( j != pPotentialAlphaBlendedSite->m_AlphaBlendSites.End() && pTmpSite != pSite )
		    {
			pTmpSite = (CHXBaseSite*)j.get_key();
			if( pTmpSite == pSite )
			{
			    pReg = (HXREGION*)*j;
			    HXUnionRegion( pEntireReg, pReg, pEntireReg );
			    break;
			}
			++j;
		    }
		}
	    }

	    newMaskRgn = CHXMacSite::_ConvertRegionToMacRegion(pEntireReg);

            CHXMacSite* pMacSite = (CHXMacSite*)zm_pOverlaySurface->m_pSite;
            // xxxbobclark should we shrink the region if we have scrollbars? I certainly think so!
            if (pMacSite->m_hHScrollBar || pMacSite->m_hVScrollBar)
            {
                Rect rgnBounds;
                ::GetRegionBounds(newMaskRgn, &rgnBounds);
                if (pMacSite->m_hHScrollBar)
                {
                    rgnBounds.bottom -= 16;
                }
                if (pMacSite->m_hVScrollBar)
                {
                    rgnBounds.right -= 16;
                }
                RgnHandle rectRgn = ::NewRgn();
                if (rectRgn)
                {
                    RectRgn(rectRgn, &rgnBounds);
                    ::SectRgn(rectRgn, newMaskRgn, newMaskRgn);
                    ::DisposeRgn(rectRgn);
                }
            }
            
	    OffsetRgn(newMaskRgn, -pEntireReg->extents.x1, -pEntireReg->extents.y1);
	    HXDestroyRegion(pEntireReg);
		
	    // xxxbobclark now intersect with current port's clip region and vis region.

	    RgnHandle trimRgn = ::NewRgn();
	    ::GetPortVisibleRegion(::GetQDGlobalsThePort(), trimRgn);
	    ::SectRgn(newMaskRgn, trimRgn, newMaskRgn);

	    if (1 /*pSite->m_bIsRealPlayerTLC*/)
	    {
		::GetClip(trimRgn);
		::SectRgn(newMaskRgn, trimRgn, newMaskRgn);
	    }
	    else
	    {
		// xxxbobclark now intersect with PNxWindow's clip rect. Only if we're
		// in an embedded player; this whole mechanism relies on browsers setting
		// up clip regions before sending null events.
		HXxWindow* pWindow = pSite->GetWindow();

		if ((pWindow->x < pWindow->clipRect.left) || ((pWindow->x + pWindow->width)  > pWindow->clipRect.right) ||
		        (pWindow->y < pWindow->clipRect.top)  || ((pWindow->y + pWindow->height) > pWindow->clipRect.bottom))
		{
		    bOverlayRebuildingRequired = TRUE;
		}

		::SetRectRgn(trimRgn, pWindow->clipRect.left, pWindow->clipRect.top, pWindow->clipRect.right, pWindow->clipRect.bottom);

		// offset region
		::OffsetRgn(trimRgn, -pWindow->x, -pWindow->y);

		::SectRgn(newMaskRgn, trimRgn, newMaskRgn);
	    }
	    ::DisposeRgn(trimRgn);

	    if ( (!bOverlayRebuildingRequired) && (!zm_OverlayMaskRgn || !::EqualRgn(newMaskRgn, zm_OverlayMaskRgn)))
	    {
		bOverlayRebuildingRequired = TRUE;
	    }
	}
	
	if (bOverlayRebuildingRequired)
	{
	    // reset the workaround counter
	    sbCatchUp = CHXMacSite::zm_ListOfMacSites.GetCount();
	}
	else if (sbCatchUp > 0)
	{
	    bOverlayRebuildingRequired = TRUE;
	    sbCatchUp--;
	}
	
	if (bOverlayRebuildingRequired)
	{
	    if (!IsMacInCooperativeThread())
	    {
//		// xxxbobclark these shouldn't be here 'cause they can
//		// force it out of overlay mode even as it's switching
//		// to full-screen mode, for example.
//		retVal = HXR_FAIL;
//		goto exit;
	    }
	    else
	    {
		sLastPoint = sP;
		sLastSize = s;
		sLastSrcSize = srcSize;
                
                if (!newMaskRgn && zm_OverlayMaskRgn)
                {
                    // CleanUpOverlay is going to clear out
                    // zm_OverlayMaskRgn. Since newMaskRgn is
                    // null and zm_OverlayMaskRgn exists we know
                    // that we're in the sbCatchUp workaround,
                    // and we need to remember the mask region
                    // around the CleanUpOverlay function call.
                    newMaskRgn = ::NewRgn();
                    ::CopyRgn(zm_OverlayMaskRgn, newMaskRgn);
                }
		CleanUpOverlay();

		if (newMaskRgn)
		{
		    HX_ASSERT(!zm_OverlayMaskRgn);
		    zm_OverlayMaskRgn = newMaskRgn;
		    newMaskRgn = NULL;
		}
		HX_ASSERT(zm_OverlayMaskRgn);
		
		ConstructOverlay(sP.h, sP.v, s.cx, s.cy, srcSize.cx, srcSize.cy, zm_OverlayMaskRgn);
	    }
	}
	if (newMaskRgn)
	{
	    ::DisposeRgn(newMaskRgn);
	}
    }
    else
    {
	retVal = HXR_FAIL;
	goto exit;
    }

    if (zm_pOverlayBuf == nil || zm_nOverlayRowBytes == 0)
    {
	retVal = HXR_FAIL;
	goto exit;
    }

    *ppSurPtr = (UCHAR*)zm_pOverlayBuf;
    *pnSurfPitch = zm_nOverlayRowBytes;
    
exit:
    HX_ASSERT(savePort != nil);
    ::SetPort(savePort);
    return retVal;
}


/************************************************************************
 *  Method:
 *    CMacSurface::_UnlockInternalSurface
 */
HX_RESULT
CMacSurface::_UnlockInternalSurface(UCHAR* pSurfPtr)
{
    // On RagePro, the ImageCodecDrawBand call does not NEED to
    // be made. Since it uses a key color, whatever's drawn
    // to the overlay magically shows up through the key color.
    // The Rage128 ignores key color, though, and requires a
    // call to ImageCodecDrawBand to update the overlay. This
    // blasts through everything, obeying the mask region.
    // So if the mask region may be outdated we will not make
    // the call to ImageCodecDrawBand.
    
    if (gDumbCursorRedrawNeeded)
    {
	gDumbCursorRedrawNeeded = FALSE;
    }
    
    BOOL bDoOverlayBlit = TRUE;
    
    CHXMacSite* pSite = (CHXMacSite*)zm_pOverlaySurface->m_pSite;
    HXxPoint offset;
    offset.x = 0;
    offset.y = 0;
    pSite->GetMacContentAreaOffset(offset);
    SetOriginAndMaintainClipRgn(-offset.x, -offset.y);

    if (bDoOverlayBlit)
    {
        if (zm_SequenceID)
        {
            short err = DecompressSequenceFrameWhen(
                            zm_SequenceID,
                            (Ptr)zm_pOverlayBuf, zm_nOverlayBufferSize,
                            0, // flags
                            nil,
                            nil,
                            nil);
        }
    }
    
    SetOriginAndMaintainClipRgn(0,0);
    return HXR_OK;
}


/************************************************************************
 *  Method:
 *    CMacSurface::_SetupDCObjects
 */
void
CMacSurface::_SetupDCObjects(HXxDC hxxDC, void** phOldBrush, void** phOldPen)
{
}


/************************************************************************
 *  Method:
 *    CMacSurface::_FillRectangle
 */
void
CMacSurface::_FillRectangle(HXxDC hxxDC, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
{
    if (zm_bOverlayRequiresKeyColor)
    {
	GrafPtr savePort;
	::GetPort(&savePort);
	
	HX_ASSERT(m_pSite);
	HXxWindow* pWindow = m_pSite->GetWindow();
	
	HX_ASSERT(pWindow && pWindow->window);
	
	::SetPort((GrafPtr)pWindow->window);
	
	Rect r;
	
	r.left = left + pWindow->x;
	r.top = top + pWindow->y;
	r.right = right + pWindow->x;
	r.bottom = bottom + pWindow->y;
	
	// xxxbobclark for ATI RagePro cards, they use a key
	// color, and the key color is hardcoded. I don't
	// know, but this may change if we stumble across a
	// card that supports key colors that aren't hard-
	// coded -- or that use a DIFFERENT hard-coded one.
	
	static RGBColor keyColor = {0x0000, 0x1000, 0x0000};
	
	RGBColor hold;

⌨️ 快捷键说明

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