2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
27 #include "realmediawindowlesssite.h"
28 #include "..\..\DSUtil\DSUtil.h"
30 void DSObjects::ExtractRects(REGION
* pRegion
)
34 DWORD sizeNeeed
= GetRegionData((HRGN
)pRegion
->pOSRegion
, 0, NULL
);
36 lpRgnData
= (LPRGNDATA
)new char[sizeNeeed
];
37 DWORD returnValue
= GetRegionData((HRGN
)pRegion
->pOSRegion
, sizeNeeed
, lpRgnData
);
39 PN_VECTOR_DELETE(pRegion
->rects
);
41 pRegion
->numRects
= lpRgnData
->rdh
.nCount
;
42 pRegion
->extents
.left
= lpRgnData
->rdh
.rcBound
.left
;
43 pRegion
->extents
.top
= lpRgnData
->rdh
.rcBound
.top
;
44 pRegion
->extents
.right
= lpRgnData
->rdh
.rcBound
.right
;
45 pRegion
->extents
.bottom
= lpRgnData
->rdh
.rcBound
.bottom
;
47 if(lpRgnData
->rdh
.nCount
)
49 pRegion
->rects
= new PNxRect
[lpRgnData
->rdh
.nCount
];
51 // now extract the information.
53 for(int j
= 0; j
< (int) lpRgnData
->rdh
.nCount
;j
++)
55 RECT
* pRect
= (RECT
*)lpRgnData
->Buffer
;
56 pRegion
->rects
[j
].left
= pRect
[j
].left
;
57 pRegion
->rects
[j
].top
= pRect
[j
].top
;
58 pRegion
->rects
[j
].right
= pRect
[j
].right
;
59 pRegion
->rects
[j
].bottom
= pRect
[j
].bottom
;
63 PN_VECTOR_DELETE(lpRgnData
);
65 REGION
* DSObjects::RMACreateRectRegion(int left
, int top
, int right
, int bottom
)
67 REGION
* retVal
= new REGION
;
68 retVal
->pOSRegion
= (void*)CreateRectRgn(left
, top
, right
, bottom
);
72 void DSObjects::RMASubtractRegion(REGION
* regM
, REGION
* regS
, REGION
* regD
)
74 CombineRgn((HRGN
)regD
->pOSRegion
, (HRGN
)regM
->pOSRegion
, (HRGN
)regS
->pOSRegion
, RGN_DIFF
);
77 void DSObjects::RMAUnionRegion(REGION
* reg1
, REGION
* reg2
, REGION
* regD
)
79 CombineRgn((HRGN
)regD
->pOSRegion
, (HRGN
)reg1
->pOSRegion
, (HRGN
)reg2
->pOSRegion
, RGN_OR
);
82 void DSObjects::RMAIntersectRegion(REGION
* reg1
, REGION
* reg2
, REGION
* regD
)
84 CombineRgn((HRGN
)regD
->pOSRegion
, (HRGN
)reg1
->pOSRegion
, (HRGN
)reg2
->pOSRegion
, RGN_AND
);
87 BOOL
DSObjects::RMAEqualRegion(REGION
* reg1
, REGION
* reg2
)
89 return EqualRgn((HRGN
)reg1
->pOSRegion
, (HRGN
)reg2
->pOSRegion
)
90 && !memcmp(®1
->extents
, ®2
->extents
, sizeof(PNxRect
)) ? TRUE
: FALSE
;
92 void DSObjects::RMADestroyRegion(REGION
* reg
)
94 if(reg
) DeleteObject((HRGN
)reg
->pOSRegion
),
95 PN_VECTOR_DELETE(reg
->rects
);
98 REGION
* DSObjects::RMACreateRegion()
100 return RMACreateRectRegion(0,0,0,0);
104 // CRealMediaWindowlessSite
107 CRealMediaWindowlessSite::CRealMediaWindowlessSite(HRESULT
& hr
, IUnknown
* pContext
, CRealMediaWindowlessSite
* pParentSite
, IUnknown
* pUnkOuter
)
108 : CUnknown(NAME("CRealMediaWindowlessSite"), pUnkOuter
, &hr
)
109 , m_pContext(pContext
)
110 , m_pParentSite(pParentSite
)
112 , m_fDamaged(false), m_fInRedraw(false), m_fIsVisible(true)
114 , m_pRegion(NULL
), m_pRegionWithoutChildren(NULL
)
116 m_size
.cx
= m_size
.cy
= 0;
117 m_position
.x
= m_position
.y
= 0;
119 memset(&m_lastBitmapInfo
, 0, sizeof(m_lastBitmapInfo
));
123 if(!m_pContext
|| !m_pCCF
)
129 m_pCCF
->CreateInstance(CLSID_IRMAValues
, (void**)&m_pValues
);
132 CRealMediaWindowlessSite::~CRealMediaWindowlessSite()
134 POSITION pos
= m_pChildren
.GetHeadPosition();
135 while(pos
) DestroyChild(m_pChildren
.GetNext(pos
));
137 RMADestroyRegion(m_pRegion
);
138 RMADestroyRegion(m_pRegionWithoutChildren
);
141 STDMETHODIMP
CRealMediaWindowlessSite::NonDelegatingQueryInterface(REFIID riid
, void** ppv
)
146 QI2(IRMASiteWindowless
)
147 QI2(IRMAVideoSurface
)
148 (m_pValues
&& m_pValues
->QueryInterface(riid
, ppv
) == PNR_OK
) ? PNR_OK
:
149 CUnknown::NonDelegatingQueryInterface(riid
, ppv
);
154 void CRealMediaWindowlessSite::GetTopLeft(PNxPoint
* pPoint
)
156 pPoint
->x
+= m_position
.x
;
157 pPoint
->y
+= m_position
.y
;
160 m_pParentSite
->GetTopLeft(pPoint
);
163 REGION
* CRealMediaWindowlessSite::GetRegion()
170 void CRealMediaWindowlessSite::RecomputeRegion()
172 if(m_pParentSite
) m_pParentSite
->RecomputeRegion();
173 else InternalRecomputeRegion();
176 void CRealMediaWindowlessSite::InternalRecomputeRegion()
180 POSITION pos
= m_pChildren
.GetHeadPosition();
183 CRealMediaWindowlessSite
* pSite
= (CRealMediaWindowlessSite
*)(IRMASite
*)m_pChildren
.GetNext(pos
);
184 if(pSite
) pSite
->InternalRecomputeRegion();
188 void CRealMediaWindowlessSite::ComputeRegion()
190 REGION
* pTempRegion
= NULL
;
194 pTempRegion
= RMACreateRegion();
195 RMAUnionRegion(pTempRegion
, m_pRegion
, pTempRegion
);
196 RMADestroyRegion(m_pRegion
);
199 if(m_pRegionWithoutChildren
)
201 RMADestroyRegion(m_pRegionWithoutChildren
);
204 PNxPoint topleft
= {0,0};
205 GetTopLeft(&topleft
);
209 m_pRegionWithoutChildren
= RMACreateRectRegion(topleft
.x
, topleft
.y
, topleft
.x
+ m_size
.cx
, topleft
.y
+ m_size
.cy
);
213 RMAIntersectRegion(m_pRegionWithoutChildren
, m_pParentSite
->m_pRegionWithoutChildren
, m_pRegionWithoutChildren
);
215 POSITION pos
= m_pParentSite
->m_pChildren
.GetHeadPosition();
218 CRealMediaWindowlessSite
* pSiblingSite
= (CRealMediaWindowlessSite
*)(IRMASite
*)m_pParentSite
->m_pChildren
.GetNext(pos
);
219 if(pSiblingSite
!= this)
222 pSiblingSite
->GetZOrder(zOrder
);
224 if(zOrder
> m_lZOrder
&& pSiblingSite
->IsSiteVisible())
226 pSiblingSite
->SubtractSite(m_pRegionWithoutChildren
);
232 m_pRegion
= RMACreateRegion();
233 RMAUnionRegion(m_pRegion
, m_pRegionWithoutChildren
, m_pRegion
);
235 POSITION pos
= m_pChildren
.GetHeadPosition();
238 CRealMediaWindowlessSite
* pChildSite
= (CRealMediaWindowlessSite
*)(IRMASite
*)m_pChildren
.GetNext(pos
);
239 if(pChildSite
->IsSiteVisible()) pChildSite
->SubtractSite(m_pRegion
);
244 m_pRegionWithoutChildren
= RMACreateRectRegion(0,0,0,0);
245 m_pRegion
= RMACreateRectRegion(0,0,0,0);
248 if(pTempRegion
&& !RMAEqualRegion(m_pRegion
, pTempRegion
))
253 RMADestroyRegion(pTempRegion
);
256 void CRealMediaWindowlessSite::SubtractSite(REGION
* pRegion
)
259 memset(&topLeft
, 0, sizeof(PNxPoint
));
260 GetTopLeft(&topLeft
);
262 REGION
* pTempRegion
= RMACreateRectRegion(topLeft
.x
, topLeft
.y
, topLeft
.x
+ m_size
.cx
, topLeft
.y
+ m_size
.cy
);
264 RMASubtractRegion(pRegion
, pTempRegion
, pRegion
);
265 RMADestroyRegion(pTempRegion
);
268 void CRealMediaWindowlessSite::UpdateZOrder(CRealMediaWindowlessSite
* pUpdatedChildSite
, INT32 lOldZOrder
, INT32 lNewZOrder
)
270 POSITION pos
= m_pChildren
.GetHeadPosition();
273 CRealMediaWindowlessSite
* pSite
= (CRealMediaWindowlessSite
*)(IRMASite
*)m_pChildren
.GetNext(pos
);
276 pSite
->GetZOrder(lItsOldZOrder
);
278 if(pSite
!= pUpdatedChildSite
)
280 if(lOldZOrder
< lNewZOrder
)
282 if(lItsOldZOrder
>= lOldZOrder
&& lItsOldZOrder
< lNewZOrder
)
284 pSite
->SetInternalZOrder(lItsOldZOrder
-1);
289 if(lItsOldZOrder
>= lNewZOrder
&& lItsOldZOrder
< lOldZOrder
)
291 pSite
->SetInternalZOrder(lItsOldZOrder
+1);
297 pSite
->SetInternalZOrder(lNewZOrder
);
302 void CRealMediaWindowlessSite::SetInternalZOrder(INT32 lZOrder
)
307 // IRMASiteWindowless
309 STDMETHODIMP
CRealMediaWindowlessSite::EventOccurred(PNxEvent
* /*IN*/ pEvent
)
311 return PNR_NOTIMPL
; /* not necessary within our implementation */
314 STDMETHODIMP_(PNxWindow
*) CRealMediaWindowlessSite::GetParentWindow()
321 STDMETHODIMP
CRealMediaWindowlessSite::AttachUser(IRMASiteUser
* /*IN*/ pUser
)
323 HRESULT hr
= PNR_FAIL
;
325 if(m_pUser
) return PNR_UNEXPECTED
;
327 if(CComQIPtr
<IRMASite
, &IID_IRMASite
> pOuterSite
= GetOwner())
328 hr
= pUser
->AttachSite(pOuterSite
);
336 STDMETHODIMP
CRealMediaWindowlessSite::DetachUser()
340 if(!m_pUser
) return PNR_UNEXPECTED
;
342 hr
= m_pUser
->DetachSite();
350 STDMETHODIMP
CRealMediaWindowlessSite::GetUser(REF(IRMASiteUser
*) /*OUT*/ pUser
)
354 if(!m_pUser
) return PNR_UNEXPECTED
;
356 (pUser
= m_pUser
)->AddRef();
361 STDMETHODIMP
CRealMediaWindowlessSite::CreateChild(REF(IRMASite
*) /*OUT*/ pChildSite
)
365 CComPtr
<IRMASite
> pSite
=
366 (IRMASite
*)new CRealMediaWindowlessSite(hr
, m_pContext
, this);
368 if(FAILED(hr
) || !pSite
)
371 pChildSite
= pSite
.Detach();
373 m_pChildren
.AddTail(pChildSite
);
378 STDMETHODIMP
CRealMediaWindowlessSite::DestroyChild(IRMASite
* /*IN*/ pChildSite
)
380 if(POSITION pos
= m_pChildren
.Find(pChildSite
))
382 m_pChildren
.RemoveAt(pos
);
386 return PNR_UNEXPECTED
;
389 STDMETHODIMP
CRealMediaWindowlessSite::AttachWatcher(IRMASiteWatcher
* /*IN*/ pWatcher
)
391 if(m_pWatcher
) return PNR_UNEXPECTED
;
393 if(m_pWatcher
= pWatcher
)
394 m_pWatcher
->AttachSite((IRMASite
*)this);
399 STDMETHODIMP
CRealMediaWindowlessSite::DetachWatcher()
401 if(!m_pWatcher
) return PNR_UNEXPECTED
;
403 m_pWatcher
->DetachSite();
409 STDMETHODIMP
CRealMediaWindowlessSite::SetPosition(PNxPoint position
)
415 hr
= m_pWatcher
->ChangingPosition(m_position
, position
);
420 m_position
= position
;
422 POSITION pos
= m_pPassiveWatchers
.GetHeadPosition();
423 while(pos
) m_pPassiveWatchers
.GetNext(pos
)->PositionChanged(&position
);
431 STDMETHODIMP
CRealMediaWindowlessSite::GetPosition(REF(PNxPoint
) position
)
433 position
= m_position
;
437 STDMETHODIMP
CRealMediaWindowlessSite::SetSize(PNxSize size
)
443 hr
= m_pWatcher
->ChangingSize(m_size
, size
);
446 if(PNR_OK
== hr
&& size
.cx
!= 0 && size
.cy
!= 0)
450 POSITION pos
= m_pPassiveWatchers
.GetHeadPosition();
451 while(pos
) m_pPassiveWatchers
.GetNext(pos
)->SizeChanged(&size
);
459 STDMETHODIMP
CRealMediaWindowlessSite::GetSize(REF(PNxSize
) size
)
465 STDMETHODIMP
CRealMediaWindowlessSite::DamageRect(PNxRect rect
)
471 STDMETHODIMP
CRealMediaWindowlessSite::DamageRegion(PNxRegion region
)
477 STDMETHODIMP
CRealMediaWindowlessSite::ForceRedraw()
479 // make sure we have a visible window and are not re-enterering and we have damage
480 if(!m_fInRedraw
&& m_fDamaged
&& m_fIsVisible
)
484 PNxEvent event
= {RMA_SURFACE_UPDATE
, NULL
, (IRMAVideoSurface
*)this, NULL
, 0, 0};
485 m_pUser
->HandleEvent(&event
);
496 STDMETHODIMP
CRealMediaWindowlessSite::UpdateSiteWindow(PNxWindow
* /*IN*/ pWindow
)
501 STDMETHODIMP
CRealMediaWindowlessSite::ShowSite(BOOL bShow
)
503 m_fIsVisible
= !!bShow
;
508 STDMETHODIMP_(BOOL
) CRealMediaWindowlessSite::IsSiteVisible()
510 BOOL fIsVisible
= m_fIsVisible
;
511 if(m_pParentSite
) fIsVisible
= fIsVisible
&& m_pParentSite
->IsSiteVisible();
515 STDMETHODIMP
CRealMediaWindowlessSite::SetZOrder(INT32 lZOrder
)
517 if(!m_pParentSite
) return PNR_UNEXPECTED
;
519 if(lZOrder
== -1 || lZOrder
>= (INT32
)m_pParentSite
->GetNumberOfChildSites())
520 lZOrder
= m_pParentSite
->GetNumberOfChildSites() - 1;
522 if(m_lZOrder
!= lZOrder
)
523 m_pParentSite
->UpdateZOrder(this, m_lZOrder
, lZOrder
);
530 STDMETHODIMP
CRealMediaWindowlessSite::GetZOrder(REF(INT32
) lZOrder
)
532 if(!m_pParentSite
) return PNR_UNEXPECTED
;
537 STDMETHODIMP
CRealMediaWindowlessSite::MoveSiteToTop()
539 if(!m_pParentSite
) return PNR_UNEXPECTED
;
543 STDMETHODIMP
CRealMediaWindowlessSite::GetVideoSurface(REF(IRMAVideoSurface
*) pSurface
)
545 (pSurface
= (IRMAVideoSurface
*)this)->AddRef();
549 STDMETHODIMP_(UINT32
) CRealMediaWindowlessSite::GetNumberOfChildSites()
551 return (UINT32
)m_pChildren
.GetCount();
554 STDMETHODIMP
CRealMediaWindowlessSite::AddPassiveSiteWatcher(IRMAPassiveSiteWatcher
* pWatcher
)
556 m_pPassiveWatchers
.AddTail(pWatcher
);
560 STDMETHODIMP
CRealMediaWindowlessSite::RemovePassiveSiteWatcher(IRMAPassiveSiteWatcher
* pWatcher
)
562 if(POSITION pos
= m_pPassiveWatchers
.Find(pWatcher
))
564 m_pPassiveWatchers
.RemoveAt(pos
);
568 return PNR_UNEXPECTED
;
571 STDMETHODIMP
CRealMediaWindowlessSite::SetCursor(PNxCursor cursor
, REF(PNxCursor
) oldCursor
)
578 void CRealMediaWindowlessSite::IntersectRect(PNxRect
* pRect
, PNxRect
* pBox
, PNxRect
* pRetVal
)
580 pRetVal
->left
= max(pRect
->left
, pBox
->left
);
581 pRetVal
->top
= max(pRect
->top
, pBox
->top
);
582 pRetVal
->right
= min(pRect
->right
, pBox
->right
);
583 pRetVal
->bottom
= min(pRect
->bottom
, pBox
->bottom
);
588 bool CRealMediaWindowlessSite::GetBltService(IRMAVideoSurface
** ppBltService
)
596 fRet
= m_pParentSite
->GetBltService(ppBltService
);
598 else if(m_pBltService
)
600 (*ppBltService
= m_pBltService
)->AddRef();
608 void CRealMediaWindowlessSite::SetBltService(IRMAVideoSurface
* pBltService
)
610 m_pBltService
= pBltService
;
615 STDMETHODIMP
CRealMediaWindowlessSite::Blt(UCHAR
* /*IN*/ pImageData
, RMABitmapInfoHeader
* /*IN*/ pBitmapInfo
, REF(PNxRect
) /*IN*/ inDestRect
, REF(PNxRect
) /*IN*/ inSrcRect
)
617 BeginOptimizedBlt(pBitmapInfo
);
618 return OptimizedBlt(pImageData
, inDestRect
, inSrcRect
);
621 STDMETHODIMP
CRealMediaWindowlessSite::BeginOptimizedBlt(RMABitmapInfoHeader
* /*IN*/ pBitmapInfo
)
623 if(memcmp(&m_bitmapInfo
, pBitmapInfo
, sizeof(RMABitmapInfoHeader
)))
625 memcpy(&m_bitmapInfo
, pBitmapInfo
, sizeof(RMABitmapInfoHeader
));
627 // format of image has changed somehow.
628 // do something here if this affects you.
632 CComPtr<IRMAVideoSurface> pBltService;
633 GetBltService(&pBltService);
635 return PNR_UNEXPECTED;
637 RMA_COMPRESSION_TYPE ulType = (RMA_COMPRESSION_TYPE)-1;
638 pBltService->GetPreferredFormat(ulType);
640 if(pBitmapInfo->biCompression != ulType)
641 return PNR_UNEXPECTED;
646 STDMETHODIMP
CRealMediaWindowlessSite::OptimizedBlt(UCHAR
* /*IN*/ pImageBits
, REF(PNxRect
) /*IN*/ rDestRect
, REF(PNxRect
) /*IN*/ rSrcRect
)
648 CComPtr
<IRMAVideoSurface
> pBltService
;
649 GetBltService(&pBltService
);
651 REGION
* pRegion
= GetRegion();
653 if(!pBltService
|| !pRegion
)
654 return PNR_UNEXPECTED
;
657 memset(&origin
, 0, sizeof(PNxPoint
));
659 PNxRect adjustedDestRect
;
660 adjustedDestRect
.left
= rDestRect
.left
+ origin
.x
;
661 adjustedDestRect
.top
= rDestRect
.top
+ origin
.y
;
662 adjustedDestRect
.right
= rDestRect
.right
+ origin
.x
;
663 adjustedDestRect
.bottom
= rDestRect
.bottom
+ origin
.y
;
665 for(int i
= 0; i
< pRegion
->numRects
; i
++)
667 PNxRect
* pRect
= pRegion
->rects
+i
;
669 // intersect the dest rect with the rect from the
670 // region to get the final dest rect.
671 PNxRect finalDestRect
;
672 IntersectRect(&adjustedDestRect
, pRect
, &finalDestRect
);
674 // now compute the src rect for this blt.
675 double xStretch
= (double) (rDestRect
.right
- rDestRect
.left
) / (double) (rSrcRect
.right
- rSrcRect
.left
);
676 double yStretch
= (double) (rDestRect
.bottom
- rDestRect
.top
) / (double) (rSrcRect
.bottom
- rSrcRect
.top
);
678 PNxRect finalSrcRect
;
679 finalSrcRect
.left
= (INT32
)((double)(finalDestRect
.left
-origin
.x
) / xStretch
+ 0.5);
680 finalSrcRect
.top
= (INT32
)((double)(finalDestRect
.top
-origin
.y
) / yStretch
+ 0.5);
681 finalSrcRect
.right
= (INT32
)((double)(finalDestRect
.right
-origin
.x
) / xStretch
+ 0.5);
682 finalSrcRect
.bottom
= (INT32
)((double)(finalDestRect
.bottom
-origin
.y
) / yStretch
+ 0.5);
684 pBltService
->Blt(pImageBits
, &m_bitmapInfo
, finalDestRect
, finalSrcRect
);
690 STDMETHODIMP
CRealMediaWindowlessSite::EndOptimizedBlt()
692 memset(&m_bitmapInfo
, 0, sizeof(m_bitmapInfo
));
696 STDMETHODIMP
CRealMediaWindowlessSite::GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE
) /*OUT*/ ulType
)
698 ulType
= m_bitmapInfo
.biCompression
;
702 STDMETHODIMP
CRealMediaWindowlessSite::GetPreferredFormat(REF(RMA_COMPRESSION_TYPE
) /*OUT*/ ulType
)
704 CComPtr
<IRMAVideoSurface
> pBltService
;
705 GetBltService(&pBltService
);
707 return PNR_UNEXPECTED
;
709 return pBltService
->GetPreferredFormat(ulType
);