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
25 #include "DX9SubPic.h"
31 CDX9SubPic::CDX9SubPic(IDirect3DSurface9
* pSurface
)
32 : m_pSurface(pSurface
)
34 D3DSURFACE_DESC d3dsd
;
35 ZeroMemory(&d3dsd
, sizeof(d3dsd
));
36 if(SUCCEEDED(m_pSurface
->GetDesc(&d3dsd
)))
38 m_maxsize
.SetSize(d3dsd
.Width
, d3dsd
.Height
);
39 CRect
allSpd(0, 0, d3dsd
.Width
, d3dsd
.Height
);
40 //m_rcDirty.SetRect(0, 0, d3dsd.Width, d3dsd.Height);
41 m_rectListDirty
.AddTail(allSpd
);
47 STDMETHODIMP_(void*) CDX9SubPic::GetObject() const
49 CComPtr
<IDirect3DTexture9
> pTexture
;
50 if(SUCCEEDED(m_pSurface
->GetContainer(IID_IDirect3DTexture9
, (void**)&pTexture
)))
51 return (void*)(IDirect3DTexture9
*)pTexture
;
56 STDMETHODIMP
CDX9SubPic::GetDesc(SubPicDesc
& spd
) const
58 D3DSURFACE_DESC d3dsd
;
59 ZeroMemory(&d3dsd
, sizeof(d3dsd
));
60 if(FAILED(m_pSurface
->GetDesc(&d3dsd
)))
67 d3dsd
.Format
== D3DFMT_A8R8G8B8
? 32 :
68 d3dsd
.Format
== D3DFMT_A4R4G4B4
? 16 : 0;
71 spd
.vidrect
= m_vidrect
;
76 STDMETHODIMP
CDX9SubPic::CopyTo(ISubPic
* pSubPic
)
79 if(FAILED(hr
= __super::CopyTo(pSubPic
)))
82 if(m_rectListDirty
.IsEmpty())
85 CComPtr
<IDirect3DDevice9
> pD3DDev
;
86 if(!m_pSurface
|| FAILED(m_pSurface
->GetDevice(&pD3DDev
)) || !pD3DDev
)
89 hr
= pD3DDev
->UpdateTexture((IDirect3DTexture9
*)GetObject(), (IDirect3DTexture9
*)pSubPic
->GetObject());
91 return SUCCEEDED(hr
) ? S_OK
: E_FAIL
;
94 STDMETHODIMP
CDX9SubPic::ClearDirtyRect(DWORD color
)
96 if(m_rectListDirty
.IsEmpty())
99 CComPtr
<IDirect3DDevice9
> pD3DDev
;
100 if(!m_pSurface
|| FAILED(m_pSurface
->GetDevice(&pD3DDev
)) || !pD3DDev
)
104 if(SUCCEEDED(Lock(spd
)))
106 POSITION pos
= m_rectListDirty
.GetHeadPosition();
109 CRect
& cRect
= m_rectListDirty
.GetNext(pos
);
110 int h
= cRect
.Height();
112 BYTE
* ptr
= (BYTE
*)spd
.bits
+ spd
.pitch
*(cRect
.top
) + (cRect
.left
*spd
.bpp
>>3);
118 WORD
* start
= (WORD
*)ptr
;
119 WORD
* end
= start
+ cRect
.Width();
120 while(start
< end
) *start
++ = (WORD
)color
;
124 else if(spd
.bpp
== 32)
128 DWORD
* start
= (DWORD
*)ptr
;
129 DWORD
* end
= start
+ cRect
.Width();
130 while(start
< end
) *start
++ = color
;
137 DWORD* ptr = (DWORD*)bm.bits;
138 DWORD* end = ptr + bm.h*bm.wBytes/4;
139 while(ptr < end) *ptr++ = color;
144 // HRESULT hr = pD3DDev->ColorFill(m_pSurface, m_rcDirty, color);
149 STDMETHODIMP
CDX9SubPic::Lock(SubPicDesc
& spd
)
151 D3DSURFACE_DESC d3dsd
;
152 ZeroMemory(&d3dsd
, sizeof(d3dsd
));
153 if(FAILED(m_pSurface
->GetDesc(&d3dsd
)))
156 D3DLOCKED_RECT LockedRect
;
157 ZeroMemory(&LockedRect
, sizeof(LockedRect
));
158 if(FAILED(m_pSurface
->LockRect(&LockedRect
, NULL
, 0)))
165 d3dsd
.Format
== D3DFMT_A8R8G8B8
? 32 :
166 d3dsd
.Format
== D3DFMT_A4R4G4B4
? 16 : 0;
167 spd
.pitch
= LockedRect
.Pitch
;
168 spd
.bits
= LockedRect
.pBits
;
169 spd
.vidrect
= m_vidrect
;
174 STDMETHODIMP
CDX9SubPic::Unlock(CAtlList
<CRect
>* dirtyRectList
)
176 m_pSurface
->UnlockRect();
178 SetDirtyRect(dirtyRectList
);
182 STDMETHODIMP
CDX9SubPic::AlphaBlt(const RECT
* pSrc
, const RECT
* pDst
, SubPicDesc
* pTarget
)
184 ASSERT(pTarget
== NULL
);
189 CRect
src(*pSrc
), dst(*pDst
);
191 CComPtr
<IDirect3DDevice9
> pD3DDev
;
192 CComPtr
<IDirect3DTexture9
> pTexture
= (IDirect3DTexture9
*)GetObject();
193 if(!pTexture
|| FAILED(pTexture
->GetDevice(&pD3DDev
)) || !pD3DDev
)
194 return E_NOINTERFACE
;
200 D3DSURFACE_DESC d3dsd
;
201 ZeroMemory(&d3dsd
, sizeof(d3dsd
));
202 if(FAILED(pTexture
->GetLevelDesc(0, &d3dsd
)) /*|| d3dsd.Type != D3DRTYPE_TEXTURE*/)
205 float w
= (float)d3dsd
.Width
;
206 float h
= (float)d3dsd
.Height
;
215 {(float)dst
.left
, (float)dst
.top
, 0.5f
, 2.0f
, (float)src
.left
/ w
, (float)src
.top
/ h
},
216 {(float)dst
.right
, (float)dst
.top
, 0.5f
, 2.0f
, (float)src
.right
/ w
, (float)src
.top
/ h
},
217 {(float)dst
.left
, (float)dst
.bottom
, 0.5f
, 2.0f
, (float)src
.left
/ w
, (float)src
.bottom
/ h
},
218 {(float)dst
.right
, (float)dst
.bottom
, 0.5f
, 2.0f
, (float)src
.right
/ w
, (float)src
.bottom
/ h
},
221 for(int i = 0; i < countof(pVertices); i++)
223 pVertices[i].x -= 0.5;
224 pVertices[i].y -= 0.5;
228 hr
= pD3DDev
->SetTexture(0, pTexture
);
231 hr
= pD3DDev
->GetRenderState(D3DRS_ALPHABLENDENABLE
, &abe
);
232 hr
= pD3DDev
->GetRenderState(D3DRS_SRCBLEND
, &sb
);
233 hr
= pD3DDev
->GetRenderState(D3DRS_DESTBLEND
, &db
);
235 hr
= pD3DDev
->SetRenderState(D3DRS_CULLMODE
, D3DCULL_NONE
);
236 hr
= pD3DDev
->SetRenderState(D3DRS_LIGHTING
, FALSE
);
237 hr
= pD3DDev
->SetRenderState(D3DRS_ZENABLE
, FALSE
);
238 hr
= pD3DDev
->SetRenderState(D3DRS_ALPHABLENDENABLE
, TRUE
);
239 hr
= pD3DDev
->SetRenderState(D3DRS_SRCBLEND
, D3DBLEND_ONE
); // pre-multiplied src and ...
240 hr
= pD3DDev
->SetRenderState(D3DRS_DESTBLEND
, D3DBLEND_SRCALPHA
); // ... inverse alpha channel for dst
242 hr
= pD3DDev
->SetTextureStageState(0, D3DTSS_COLOROP
, D3DTOP_SELECTARG1
);
243 hr
= pD3DDev
->SetTextureStageState(0, D3DTSS_COLORARG1
, D3DTA_TEXTURE
);
244 hr
= pD3DDev
->SetTextureStageState(0, D3DTSS_ALPHAARG1
, D3DTA_TEXTURE
);
246 hr
= pD3DDev
->SetSamplerState(0, D3DSAMP_MAGFILTER
, D3DTEXF_LINEAR
);
247 hr
= pD3DDev
->SetSamplerState(0, D3DSAMP_MINFILTER
, D3DTEXF_LINEAR
);
248 hr
= pD3DDev
->SetSamplerState(0, D3DSAMP_MIPFILTER
, D3DTEXF_LINEAR
);
250 hr
= pD3DDev
->SetSamplerState(0, D3DSAMP_ADDRESSU
, D3DTADDRESS_CLAMP
);
251 hr
= pD3DDev
->SetSamplerState(0, D3DSAMP_ADDRESSV
, D3DTADDRESS_CLAMP
);
256 hr = pD3DDev->GetDeviceCaps(&d3dcaps9);
257 if(d3dcaps9.AlphaCmpCaps & D3DPCMPCAPS_LESS)
259 hr = pD3DDev->SetRenderState(D3DRS_ALPHAREF, (DWORD)0x000000FE);
260 hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
261 hr = pD3DDev->SetRenderState(D3DRS_ALPHAFUNC, D3DPCMPCAPS_LESS);
266 hr
= pD3DDev
->SetPixelShader(NULL
);
268 if(FAILED(hr
= pD3DDev
->BeginScene()))
271 hr
= pD3DDev
->SetFVF(D3DFVF_XYZRHW
| D3DFVF_TEX1
);
272 hr
= pD3DDev
->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP
, 2, pVertices
, sizeof(pVertices
[0]));
274 hr
= pD3DDev
->EndScene();
278 pD3DDev
->SetTexture(0, NULL
);
280 pD3DDev
->SetRenderState(D3DRS_ALPHABLENDENABLE
, abe
);
281 pD3DDev
->SetRenderState(D3DRS_SRCBLEND
, sb
);
282 pD3DDev
->SetRenderState(D3DRS_DESTBLEND
, db
);
291 STDMETHODIMP
CDX9SubPic::SetDirtyRect( CAtlList
<CRect
>* dirtyRectList
)
295 POSITION pos
= dirtyRectList
->GetHeadPosition();
298 CRect
& cRect
= dirtyRectList
->GetNext(pos
);
299 cRect
.InflateRect(1,1);
302 cRect
.right
= (cRect
.right
+ 127) & ~127;
303 cRect
.bottom
= (cRect
.bottom
+ 63) & ~63;
304 cRect
&= CRect(CPoint(0, 0), m_size
);
307 return __super::SetDirtyRect(dirtyRectList
);
310 // CDX9SubPicAllocator
313 CDX9SubPicAllocator::CDX9SubPicAllocator(IDirect3DDevice9
* pD3DDev
, SIZE maxsize
, bool fPow2Textures
)
314 : ISubPicAllocatorImpl(maxsize
, true, fPow2Textures
)
324 STDMETHODIMP
CDX9SubPicAllocator::ChangeDevice(IUnknown
* pDev
)
326 CComQIPtr
<IDirect3DDevice9
> pD3DDev
= pDev
;
327 if(!pD3DDev
) return E_NOINTERFACE
;
329 CAutoLock
cAutoLock(this);
332 return __super::ChangeDevice(pDev
);
335 // ISubPicAllocatorImpl
337 bool CDX9SubPicAllocator::Alloc(bool fStatic
, ISubPic
** ppSubPic
)
342 CAutoLock
cAutoLock(this);
346 CComPtr
<IDirect3DSurface9
> pSurface
;
348 int Width
= m_maxsize
.cx
;
349 int Height
= m_maxsize
.cy
;
354 while(Width
< m_maxsize
.cx
) Width
<<= 1;
355 while(Height
< m_maxsize
.cy
) Height
<<= 1;
358 CComPtr
<IDirect3DTexture9
> pTexture
;
359 if(FAILED(m_pD3DDev
->CreateTexture(Width
, Height
, 1, 0, D3DFMT_A8R8G8B8
, fStatic
?D3DPOOL_SYSTEMMEM
:D3DPOOL_DEFAULT
, &pTexture
, NULL
)))
362 if(FAILED(pTexture
->GetSurfaceLevel(0, &pSurface
)))
365 if(!(*ppSubPic
= new CDX9SubPic(pSurface
)))
368 (*ppSubPic
)->AddRef();