📄 macroot.cpp
字号:
void CMacRootSurface::CheckRectRgn( Rect r, RgnHandle rgn, Point globalOffset )
{
if ( r.bottom <= r.top || r.right <= r.left || !RectInRgn( &r, rgn ) )
{
// if the rect is empty or ain't in the region, bail.
return;
}
if ( IsRegionRectangular( rgn ) )
{
// since the region is a rectangle, add that rectangle and bail.
Rect* newRect = new Rect;
GetRegionBounds(rgn, newRect);
newRect->left += globalOffset.h;
newRect->top += globalOffset.v;
newRect->right += globalOffset.h;
newRect->bottom += globalOffset.v;
m_pVisRgnRects->AddTail( newRect );
return;
}
// we've established that it's not clearly defined, so divide and conquer.
Rect newRect1 = r;
Rect newRect2 = r;
if ( r.bottom - r.top > r.right - r.left )
{
// more vertically oriented
short interimValue = ( r.bottom + r.top ) / 2;
newRect1.bottom = interimValue;
newRect2.top = interimValue;
}
else
{
// more horizontally oriented
short interimValue = ( r.left + r.right ) / 2;
newRect1.right = interimValue;
newRect2.left = interimValue;
}
RgnHandle newRgn1 = NewRgn();
RgnHandle newRgn2 = NewRgn();
RectRgn( newRgn1, &newRect1 );
RectRgn( newRgn2, &newRect2 );
SectRgn( rgn, newRgn1, newRgn1 );
SectRgn( rgn, newRgn2, newRgn2 );
CheckRectRgn( newRect1, newRgn1, globalOffset );
CheckRectRgn( newRect2, newRgn2, globalOffset );
DisposeRgn( newRgn1 );
DisposeRgn( newRgn2 );
}
/************************************************************************
* Method:
* CMacRootSurface::UpdateRegionIfNecessary
*
*/
void
CMacRootSurface::UpdateRegionIfNecessary(Rect boundingRect, Point globalOffset, BOOL bForceItToUpdate /* = FALSE */ )
{
#if defined(_CARBON) || defined(_MAC_UNIX)
return; // xxxbobclark just to keep from crashing???
#else
HX_ASSERT(!HXMM_ATINTERRUPT());
if (HXMM_ATINTERRUPT()) return;
GrafPtr savePort;
::GetPort(&savePort);
WindowPtr macWindow = m_pSite->GetWindow() ? (WindowPtr)m_pSite->GetWindow()->window : NULL;
if (CHXMacSite::zm_bFullScreenActive)
{
CHXMacSite* pMacSite = (CHXMacSite*)m_pSite;
if (pMacSite->m_pHXxFullScreenWindow)
{
macWindow = (WindowPtr)pMacSite->m_pHXxFullScreenWindow->window;
}
}
HX_ASSERT(macWindow);
if (!macWindow) return;
#if defined(_CARBON) || defined(_MAC_UNIX)
::SetPort( GetWindowPort( macWindow ) );
#else
::SetPort(macWindow);
#endif
RgnHandle theClippedVisRgn = ::NewRgn();
#if defined(_CARBON) || defined(_MAC_UNIX)
RgnHandle visRgn = ::NewRgn();
::GetPortVisibleRegion( GetWindowPort(macWindow), visRgn );
RgnHandle clipRgn = ::NewRgn();
::GetPortClipRegion( GetWindowPort(macWindow), clipRgn );
::SectRgn( visRgn, clipRgn, theClippedVisRgn );
::DisposeRgn( clipRgn );
::DisposeRgn( visRgn );
#else
::SectRgn( macWindow->visRgn, macWindow->clipRgn, theClippedVisRgn );
#endif
// first, dispose and null out m_LastVisRgn if necessary (or forced)
if ( m_LastVisRgn && ( bForceItToUpdate || !::EqualRgn(theClippedVisRgn, m_LastVisRgn) ) )
{
::DisposeRgn(m_LastVisRgn);
m_LastVisRgn = NULL;
}
if (!m_LastVisRgn)
{
m_LastVisRgn = ::NewRgn();
::CopyRgn(theClippedVisRgn, m_LastVisRgn);
RgnHandle interimRgn = ::NewRgn();
::RectRgn(interimRgn, &boundingRect);
::SectRgn(m_LastVisRgn, interimRgn, interimRgn);
while (m_pVisRgnRects->GetCount())
{
Rect* r = (Rect*)m_pVisRgnRects->RemoveHead();
delete r;
}
CheckRectRgn(boundingRect, interimRgn, globalOffset);
// RegionToRectsByNoodlingThroughRegion(interimRgn, globalOffset, m_VisRgnRects);
::DisposeRgn(interimRgn);
}
::DisposeRgn(theClippedVisRgn);
::SetPort(savePort);
#endif
}
/************************************************************************
* Method:
* CMacRootSurface::_PreFlightBlt
*
* This is called AFTER the current sub-rectangle has been determined,
* but BEFORE any assumptions about screen depth or anything have been
* made. Basically this is where I can hijack the cross-platform code's
* assumptions and surreptitiously slide in an appropriate
* m_pCompositionSurface and other variables.
*
*/
void
CMacRootSurface::_PreFlightBlt(HXxRect& dst)
{
if (!m_bItsOKToDoAnInterruptBlit) return;
m_pCompositionSurface = nil;
m_nBlitDepthEnum = -1;
Rect r;
r.left = dst.left + m_LocalToGlobalCoords.h;
r.top = dst.top + m_LocalToGlobalCoords.v;
r.right = dst.right + m_LocalToGlobalCoords.h;
r.bottom = dst.bottom + m_LocalToGlobalCoords.v;
#ifdef USE_LOW_LEVEL_QT_API
int i = zm_uNumberOfAttachedDevices;
#else
for (int i = 0; i < zm_uNumberOfAttachedDevices; i++)
#endif
{
Rect intersectionRect;
if ((i == zm_uNumberOfAttachedDevices) || (::SectRect(&r, &(**zm_AttachedDevice[i]).gdRect, &intersectionRect)))
{
// now figure out which GWorld we need to use.
// XXXbobclark I'm starting out with a copy-n-paste of
// _CreateCompositionSurface(). Ewww. But the problem is that
// we don't know -- until now -- which depths and therefore
// which GWorlds we need. Dayum. ...And what makes it worse is
// that it might be interrupt time before stuff's created. That
// will be a weird circumstance -- and one where the blit won't
// actually succeed -- but it might screw things up in the
// meantime, like if it tries to blit into the NULL composition
// surface. Crash. So maybe if it fails everywhere else I'll
// force the composition surface to be the 32-bit one that's
// created in _CreateCompositionSurface just so the color
// converter has SOMETHING to blit into even though it will
// subsequently get ignored. Shee-it.
// All (potentially three) offscreens will be full-sized. This
// could be a "waste" of memory, but solving it is excruciatingly
// subtle and has many tendrils, such as telling the color converter
// to convert into non 0,0-based rectangles, yeesh. The good news
// -- and an improvement over the older site code -- is that it
// only color-converts into the parts of the offscreen that
// eventually gets blitted to screen. So there's not a lot of
// wasted color conversion.
PixMapHandle thePMH = NULL;
int pixelSize = 0;
INT32 whichDepth;
#ifdef USE_LOW_LEVEL_QT_API
if (i == zm_uNumberOfAttachedDevices)
{
whichDepth = kYUVDepth;
}
else
#endif
{
thePMH = (**zm_AttachedDevice[i]).gdPMap;
pixelSize = (**thePMH).pixelSize;
whichDepth = DepthToDepthEnum(pixelSize);
}
if (m_RootSurfaceGWorld[whichDepth])
{
// now see if it needs to be reinitialized.
Rect thePortRect;
#if defined(_CARBON) || defined(_MAC_UNIX)
GetPortBounds(m_RootSurfaceGWorld[whichDepth], &thePortRect);
#else
thePortRect = m_RootSurfaceGWorld[whichDepth]->portRect;
#endif
BOOL bNeedToRecreate = FALSE;
if (m_compositionSize.cx > thePortRect.right - thePortRect.left) bNeedToRecreate = TRUE;
if (m_compositionSize.cy > thePortRect.bottom - thePortRect.top) bNeedToRecreate = TRUE;
#ifdef USE_LOW_LEVEL_QT_API
if (whichDepth == kYUVDepth)
{
// xxxbobclark if it's using YUV then the QT calls assume that the whole
// GWorld is being used, so using just the upper-left portion
// doesn't work.
if (m_compositionSize.cx != thePortRect.right-thePortRect.left) bNeedToRecreate = TRUE;
if (m_compositionSize.cy != thePortRect.bottom-thePortRect.top) bNeedToRecreate = TRUE;
}
#endif
if (bNeedToRecreate)
{
::UnlockPixels(m_RootGWorldPixMap[whichDepth]);
::DisposeGWorld(m_RootSurfaceGWorld[whichDepth]);
m_RootSurfaceGWorld[whichDepth] = nil;
m_RootGWorldPixMap[whichDepth] = nil;
}
}
if (!m_RootSurfaceGWorld[whichDepth])
{
// need to (re)create it
Rect r;
::SetRect(&r, 0, 0, m_compositionSize.cx, m_compositionSize.cy);
#ifdef USE_LOW_LEVEL_QT_API
if (whichDepth == kYUVDepth)
{
::QTNewGWorld(&m_RootSurfaceGWorld[whichDepth], 'yuvs', &r, nil, nil, useTempMem | 16 | 32);
if (!m_RootSurfaceGWorld[whichDepth])
{
::QTNewGWorld(&m_RootSurfaceGWorld[whichDepth], 'yuvs', &r, nil, nil, useTempMem | 32);
}
if (!m_RootSurfaceGWorld[whichDepth])
{
::QTNewGWorld(&m_RootSurfaceGWorld[whichDepth], 'yuvs', &r, nil, nil, useTempMem | 16);
}
if (!m_RootSurfaceGWorld[whichDepth])
{
::QTNewGWorld(&m_RootSurfaceGWorld[whichDepth], 'yuvs', &r, nil, nil, 16 | 32);
}
if (!m_RootSurfaceGWorld[whichDepth])
{
::QTNewGWorld(&m_RootSurfaceGWorld[whichDepth], 'yuvs', &r, nil, nil, 32);
}
if (!m_RootSurfaceGWorld[whichDepth])
{
::QTNewGWorld(&m_RootSurfaceGWorld[whichDepth], 'yuvs', &r, nil, nil, 16);
}
if (!m_RootSurfaceGWorld[whichDepth])
{
::QTNewGWorld(&m_RootSurfaceGWorld[whichDepth], 'yuvs', &r, nil, nil, useTempMem);
}
if (!m_RootSurfaceGWorld[whichDepth])
{
return;
}
}
else
#endif
{
::NewGWorld(&m_RootSurfaceGWorld[whichDepth], pixelSize, &r, nil, nil, useTempMem);
if (!m_RootSurfaceGWorld[whichDepth])
{
::NewGWorld(&m_RootSurfaceGWorld[whichDepth], pixelSize, &r, nil, nil, 0);
if (!m_RootSurfaceGWorld[whichDepth]) return;
}
}
#if defined(_CARBON) || defined(_MAC_UNIX)
m_RootGWorldPixMap[whichDepth] = GetPortPixMap(m_RootSurfaceGWorld[whichDepth]);
#else
m_RootGWorldPixMap[whichDepth] = m_RootSurfaceGWorld[whichDepth]->portPixMap;
#endif
::LockPixels(m_RootGWorldPixMap[whichDepth]);
}
// OK now the offscreen stuff should all be reinitialized if
// it came to that... in any case we're now ready to do the
// actual work? nah... kludgey? nah... surreptitious! stuff.
if (m_RootSurfaceGWorld[whichDepth] && m_RootGWorldPixMap[whichDepth])
{
m_pCompositionSurface = (unsigned char*)::GetPixBaseAddr(m_RootGWorldPixMap[whichDepth]);
m_nBlitDepthEnum = whichDepth;
Rect hold;
#if defined(_CARBON) || defined(_MAC_UNIX)
GetPortBounds(m_RootSurfaceGWorld[whichDepth], &hold);
#else
hold = m_RootSurfaceGWorld[whichDepth]->portRect;
#endif
m_allocatedCompositionSize.cx = hold.right-hold.left;
m_allocatedCompositionSize.cy = hold.bottom-hold.top;
m_nCompositionPitch = (**m_RootGWorldPixMap[whichDepth]).rowBytes & 0x3fff;
m_boundsRect.left = 0;
m_boundsRect.top = 0;
m_boundsRect.right = m_allocatedCompositionSize.cx;
m_boundsRect.bottom = m_allocatedCompositionSize.cy;
switch (whichDepth)
{
case kThirtyTwoBitDepth:
m_nCompositionSurfaceCID = CID_RGB32;
break;
case kSixteenBitDepth:
m_nCompositionSurfaceCID = CID_RGB555;
break;
#ifdef USE_LOW_LEVEL_QT_API
case kYUVDepth:
m_nCompositionSurfaceCID = CID_YUY2;
break;
#endif
default:
m_nCompositionSurfaceCID = CID_RGB8;
break;
}
}
}
}
if (!m_pCompositionSurface)
{
// this is possible if we're at interrupt time and we're trying to
// blit to bad places.
if (m_RootSurfaceGWorld[kThirtyTwoBitDepth] && m_RootGWorldPixMap[kThirtyTwoBitDepth])
{
m_pCompositionSurface = (unsigned char*)GetPixBaseAddr(m_RootGWorldPixMap[kThirtyTwoBitDepth]);
m_nBlitDepthEnum = kThirtyTwoBitDepth;
m_nCompositionPitch = (**m_RootGWorldPixMap[kThirtyTwoBitDepth]).rowBytes & 0x3fff;
m_boundsRect.left = 0;
m_boundsRect.top = 0;
m_boundsRect.right = m_compositionSize.cx;
m_boundsRect.bottom = m_compositionSize.cy;
m_nCompositionSurfaceCID = CID_RGB32;
}
}
}
/************************************************************************
* Method:
* CMacRootSurface::_GetNumberOfMonitors
*
*/
UINT32 CMacRootSurface::_GetNumberOfMonitors()
{
return zm_uNumberOfAttachedDevices;
}
/************************************************************************
* Method:
* CMacRootSurface::_RectOnNthMonitor
*
*/
BOOL CMacRootSurface::_RectOnNthMonitor(HXxRect rect, UINT32 uMonitor, HXxRect& intersectRect)
{
HX_ASSERT(uMonitor < zm_uNumberOfAttachedDevices);
if (/*It's using an overlay*/1)
{
if (uMonitor == 0)
{
intersectRect = rect;
return TRUE;
}
else
{
return FALSE;
}
}
if (!m_bItsOKToDoAnInterruptBlit)
{
// XXXbobclark well, um, the thing is, if it's at interrupt time
// we'll bail out this instant; if it's at system time that means
// we can probably pass through a (possibly bogus) rectangle so
// the code in _MinimalBlt() catches it and can set m_bItsOKToAn-
// InterruptBlit to true.
intersectRect = rect;
return TRUE;
}
Rect r;
r.left = rect.left + m_LocalToGlobalCoords.h;
r.top = rect.top + m_LocalToGlobalCoords.v;
r.right = rect.right + m_LocalToGlobalCoords.h;
r.bottom = rect.bottom + m_LocalToGlobalCoords.v;
Rect intR;
if (::SectRect(&r, &(**zm_AttachedDevice[uMonitor]).gdRect, &intR))
{
intersectRect.left = intR.left - m_LocalToGlobalCoords.h;
intersectRect.top = intR.top - m_LocalToGlobalCoords.v;
intersectRect.right = intR.right - m_LocalToGlobalCoords.h;
intersectRect.bottom = intR.bottom - m_LocalToGlobalCoords.v;
return TRUE;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -