Merge branch 'bug_fix' into mru
[xy_vsfilter.git] / src / subpic / DX9SubPic.cpp
blob8e7c771ab1f124ba8f7ebe58fb624fc888cc34d3
1 /*
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)
8 * any later version.
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
22 #include "stdafx.h"
23 #include <d3d9.h>
24 #include <Vmr9.h>
25 #include "DX9SubPic.h"
28 // CDX9SubPic
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);
45 // ISubPic
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;
53 return NULL;
56 STDMETHODIMP CDX9SubPic::GetDesc(SubPicDesc& spd) const
58 D3DSURFACE_DESC d3dsd;
59 ZeroMemory(&d3dsd, sizeof(d3dsd));
60 if(FAILED(m_pSurface->GetDesc(&d3dsd)))
61 return E_FAIL;
63 spd.type = 0;
64 spd.w = m_size.cx;
65 spd.h = m_size.cy;
66 spd.bpp =
67 d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 :
68 d3dsd.Format == D3DFMT_A4R4G4B4 ? 16 : 0;
69 spd.pitch = 0;
70 spd.bits = NULL;
71 spd.vidrect = m_vidrect;
73 return S_OK;
76 STDMETHODIMP CDX9SubPic::CopyTo(ISubPic* pSubPic)
78 HRESULT hr;
79 if(FAILED(hr = __super::CopyTo(pSubPic)))
80 return hr;
82 if(m_rectListDirty.IsEmpty())
83 return S_FALSE;
85 CComPtr<IDirect3DDevice9> pD3DDev;
86 if(!m_pSurface || FAILED(m_pSurface->GetDevice(&pD3DDev)) || !pD3DDev)
87 return E_FAIL;
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())
97 return S_FALSE;
99 CComPtr<IDirect3DDevice9> pD3DDev;
100 if(!m_pSurface || FAILED(m_pSurface->GetDevice(&pD3DDev)) || !pD3DDev)
101 return E_FAIL;
103 SubPicDesc spd;
104 if(SUCCEEDED(Lock(spd)))
106 POSITION pos = m_rectListDirty.GetHeadPosition();
107 while(pos!=NULL)
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);
114 if(spd.bpp == 16)
116 while(h-- > 0)
118 WORD* start = (WORD*)ptr;
119 WORD* end = start + cRect.Width();
120 while(start < end) *start++ = (WORD)color;
121 ptr += spd.pitch;
124 else if(spd.bpp == 32)
126 while(h-- > 0)
128 DWORD* start = (DWORD*)ptr;
129 DWORD* end = start + cRect.Width();
130 while(start < end) *start++ = color;
131 ptr += spd.pitch;
137 DWORD* ptr = (DWORD*)bm.bits;
138 DWORD* end = ptr + bm.h*bm.wBytes/4;
139 while(ptr < end) *ptr++ = color;
141 Unlock(NULL);
144 // HRESULT hr = pD3DDev->ColorFill(m_pSurface, m_rcDirty, color);
146 return S_OK;
149 STDMETHODIMP CDX9SubPic::Lock(SubPicDesc& spd)
151 D3DSURFACE_DESC d3dsd;
152 ZeroMemory(&d3dsd, sizeof(d3dsd));
153 if(FAILED(m_pSurface->GetDesc(&d3dsd)))
154 return E_FAIL;
156 D3DLOCKED_RECT LockedRect;
157 ZeroMemory(&LockedRect, sizeof(LockedRect));
158 if(FAILED(m_pSurface->LockRect(&LockedRect, NULL, 0)))
159 return E_FAIL;
161 spd.type = 0;
162 spd.w = m_size.cx;
163 spd.h = m_size.cy;
164 spd.bpp =
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;
171 return S_OK;
174 STDMETHODIMP CDX9SubPic::Unlock(CAtlList<CRect>* dirtyRectList)
176 m_pSurface->UnlockRect();
178 SetDirtyRect(dirtyRectList);
179 return S_OK;
182 STDMETHODIMP CDX9SubPic::AlphaBlt(const RECT* pSrc, const RECT* pDst, SubPicDesc* pTarget)
184 ASSERT(pTarget == NULL);
186 if(!pSrc || !pDst)
187 return E_POINTER;
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;
196 HRESULT hr;
200 D3DSURFACE_DESC d3dsd;
201 ZeroMemory(&d3dsd, sizeof(d3dsd));
202 if(FAILED(pTexture->GetLevelDesc(0, &d3dsd)) /*|| d3dsd.Type != D3DRTYPE_TEXTURE*/)
203 break;
205 float w = (float)d3dsd.Width;
206 float h = (float)d3dsd.Height;
208 struct
210 float x, y, z, rhw;
211 float tu, tv;
213 pVertices[] =
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);
230 DWORD abe, sb, db;
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);
253 /*//
255 D3DCAPS9 d3dcaps9;
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);
264 *///
266 hr = pD3DDev->SetPixelShader(NULL);
268 if(FAILED(hr = pD3DDev->BeginScene()))
269 break;
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);
284 return S_OK;
286 while(0);
288 return E_FAIL;
291 STDMETHODIMP CDX9SubPic::SetDirtyRect( CAtlList<CRect>* dirtyRectList )
293 if(dirtyRectList)
295 POSITION pos = dirtyRectList->GetHeadPosition();
296 while(pos!=NULL)
298 CRect& cRect = dirtyRectList->GetNext(pos);
299 cRect.InflateRect(1,1);
300 cRect.left &= ~127;
301 cRect.top &= ~63;
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)
315 , m_pD3DDev(pD3DDev)
316 , m_maxsize(maxsize)
318 m_pD3DDev = pD3DDev;
319 m_maxsize = maxsize;
322 // ISubPicAllocator
324 STDMETHODIMP CDX9SubPicAllocator::ChangeDevice(IUnknown* pDev)
326 CComQIPtr<IDirect3DDevice9> pD3DDev = pDev;
327 if(!pD3DDev) return E_NOINTERFACE;
329 CAutoLock cAutoLock(this);
330 m_pD3DDev = pD3DDev;
332 return __super::ChangeDevice(pDev);
335 // ISubPicAllocatorImpl
337 bool CDX9SubPicAllocator::Alloc(bool fStatic, ISubPic** ppSubPic)
339 if(!ppSubPic)
340 return(false);
342 CAutoLock cAutoLock(this);
344 *ppSubPic = NULL;
346 CComPtr<IDirect3DSurface9> pSurface;
348 int Width = m_maxsize.cx;
349 int Height = m_maxsize.cy;
351 if(m_fPow2Textures)
353 Width = Height = 1;
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)))
360 return(false);
362 if(FAILED(pTexture->GetSurfaceLevel(0, &pSurface)))
363 return(false);
365 if(!(*ppSubPic = new CDX9SubPic(pSurface)))
366 return(false);
368 (*ppSubPic)->AddRef();
370 return(true);