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 "DX7SubPic.h"
31 CDX7SubPic::CDX7SubPic(IDirect3DDevice7
* pD3DDev
, IDirectDrawSurface7
* pSurface
)
32 : m_pSurface(pSurface
)
37 if(SUCCEEDED(m_pSurface
->GetSurfaceDesc(&ddsd
))) {
38 m_maxsize
.SetSize(ddsd
.dwWidth
, ddsd
.dwHeight
);
39 m_rcDirty
.SetRect(0, 0, ddsd
.dwWidth
, ddsd
.dwHeight
);
45 STDMETHODIMP_(void*) CDX7SubPic::GetObject() const
47 return (void*)(IDirectDrawSurface7
*)m_pSurface
;
50 STDMETHODIMP
CDX7SubPic::GetDesc(SubPicDesc
& spd
) const
54 if(FAILED(m_pSurface
->GetSurfaceDesc(&ddsd
))) {
61 spd
.bpp
= (WORD
)ddsd
.ddpfPixelFormat
.dwRGBBitCount
;
62 spd
.pitch
= ddsd
.lPitch
;
63 spd
.bits
= ddsd
.lpSurface
; // should be NULL
64 spd
.vidrect
= m_vidrect
;
69 // pSubPic must be a pointer to CDX7SubPic in fact because implementation of this function use an
70 // explicit cast the type of the return value of GetObject to IDirectDrawSurface7*
71 STDMETHODIMP
CDX7SubPic::CopyTo(ISubPic
* pSubPic
)
74 if(FAILED(hr
= __super::CopyTo(pSubPic
))) {
79 CPoint p
= m_rcDirty
.TopLeft();
80 hr
= m_pD3DDev
->Load((IDirectDrawSurface7
*)pSubPic
->GetObject(), &p
, (IDirectDrawSurface7
*)GetObject(), m_rcDirty
, 0);
82 return SUCCEEDED(hr
) ? S_OK
: E_FAIL
;
85 STDMETHODIMP
CDX7SubPic::ClearDirtyRect(DWORD color
)
87 if(m_rcDirty
.IsRectEmpty()) {
93 fx
.dwFillColor
= color
;
94 m_pSurface
->Blt(&m_rcDirty
, NULL
, NULL
, DDBLT_WAIT
|DDBLT_COLORFILL
, &fx
);
96 m_rcDirty
.SetRectEmpty();
101 STDMETHODIMP
CDX7SubPic::Lock(SubPicDesc
& spd
)
105 if(FAILED(m_pSurface
->Lock(NULL
, &ddsd
, DDLOCK_SURFACEMEMORYPTR
|DDLOCK_WAIT
, NULL
))) {
112 spd
.bpp
= (WORD
)ddsd
.ddpfPixelFormat
.dwRGBBitCount
;
113 spd
.pitch
= ddsd
.lPitch
;
114 spd
.bits
= ddsd
.lpSurface
;
115 spd
.vidrect
= m_vidrect
;
120 STDMETHODIMP
CDX7SubPic::Unlock(RECT
* pDirtyRect
)
122 m_pSurface
->Unlock(NULL
);
125 m_rcDirty
= *pDirtyRect
;
126 m_rcDirty
.InflateRect(1, 1);
127 m_rcDirty
&= CRect(CPoint(0, 0), m_size
);
129 m_rcDirty
= CRect(CPoint(0, 0), m_size
);
134 STDMETHODIMP
CDX7SubPic::AlphaBlt(const RECT
* pSrc
, const RECT
* pDst
, SubPicDesc
* pTarget
)
136 ASSERT(pTarget
== NULL
);
138 if(!m_pD3DDev
|| !m_pSurface
|| !pSrc
|| !pDst
) {
142 CRect
src(*pSrc
), dst(*pDst
);
149 if(FAILED(hr
= m_pSurface
->GetSurfaceDesc(&ddsd
))) {
153 float w
= (float)ddsd
.dwWidth
;
154 float h
= (float)ddsd
.dwHeight
;
161 {(float)dst
.left
, (float)dst
.top
, 0.5f
, 2.0f
, (float)src
.left
/ w
, (float)src
.top
/ h
},
162 {(float)dst
.right
, (float)dst
.top
, 0.5f
, 2.0f
, (float)src
.right
/ w
, (float)src
.top
/ h
},
163 {(float)dst
.left
, (float)dst
.bottom
, 0.5f
, 2.0f
, (float)src
.left
/ w
, (float)src
.bottom
/ h
},
164 {(float)dst
.right
, (float)dst
.bottom
, 0.5f
, 2.0f
, (float)src
.right
/ w
, (float)src
.bottom
/ h
},
167 for(ptrdiff_t i = 0; i < countof(pVertices); i++)
169 pVertices[i].x -= 0.5;
170 pVertices[i].y -= 0.5;
173 hr
= m_pD3DDev
->SetTexture(0, m_pSurface
);
175 m_pD3DDev
->SetRenderState(D3DRENDERSTATE_CULLMODE
, D3DCULL_NONE
);
176 m_pD3DDev
->SetRenderState(D3DRENDERSTATE_LIGHTING
, FALSE
);
177 m_pD3DDev
->SetRenderState(D3DRENDERSTATE_BLENDENABLE
, TRUE
);
178 m_pD3DDev
->SetRenderState(D3DRENDERSTATE_SRCBLEND
, D3DBLEND_ONE
); // pre-multiplied src and ...
179 m_pD3DDev
->SetRenderState(D3DRENDERSTATE_DESTBLEND
, D3DBLEND_SRCALPHA
); // ... inverse alpha channel for dst
181 m_pD3DDev
->SetTextureStageState(0, D3DTSS_COLOROP
, D3DTOP_SELECTARG1
);
182 m_pD3DDev
->SetTextureStageState(0, D3DTSS_COLORARG1
, D3DTA_TEXTURE
);
183 m_pD3DDev
->SetTextureStageState(0, D3DTSS_ALPHAARG1
, D3DTA_TEXTURE
);
185 m_pD3DDev
->SetTextureStageState(0, D3DTSS_MAGFILTER
, D3DTFG_LINEAR
);
186 m_pD3DDev
->SetTextureStageState(0, D3DTSS_MINFILTER
, D3DTFN_LINEAR
);
187 m_pD3DDev
->SetTextureStageState(0, D3DTSS_MIPFILTER
, D3DTFP_LINEAR
);
189 m_pD3DDev
->SetTextureStageState(0, D3DTSS_ADDRESS
, D3DTADDRESS_CLAMP
);
193 D3DDEVICEDESC7 d3ddevdesc;
194 m_pD3DDev->GetCaps(&d3ddevdesc);
195 if(d3ddevdesc.dpcTriCaps.dwAlphaCmpCaps & D3DPCMPCAPS_LESS)
197 m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)0x000000FE);
198 m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
199 m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DPCMPCAPS_LESS);
204 if(FAILED(hr
= m_pD3DDev
->BeginScene())) {
208 hr
= m_pD3DDev
->DrawPrimitive(D3DPT_TRIANGLESTRIP
,
209 D3DFVF_XYZRHW
| D3DFVF_TEX1
,
210 pVertices
, 4, D3DDP_WAIT
);
211 m_pD3DDev
->EndScene();
215 m_pD3DDev
->SetTexture(0, NULL
);
224 // CDX7SubPicAllocator
227 CDX7SubPicAllocator::CDX7SubPicAllocator(IDirect3DDevice7
* pD3DDev
, SIZE maxsize
, bool fPow2Textures
)
228 : CSubPicAllocatorImpl(maxsize
, true, fPow2Textures
)
236 STDMETHODIMP
CDX7SubPicAllocator::ChangeDevice(IUnknown
* pDev
)
238 CComQIPtr
<IDirect3DDevice7
, &IID_IDirect3DDevice7
> pD3DDev
= pDev
;
240 return E_NOINTERFACE
;
243 CAutoLock
cAutoLock(this);
246 return __super::ChangeDevice(pDev
);
249 // ISubPicAllocatorImpl
251 bool CDX7SubPicAllocator::Alloc(bool fStatic
, ISubPic
** ppSubPic
)
257 CAutoLock
cAutoLock(this);
261 ddsd
.dwFlags
= DDSD_CAPS
|DDSD_WIDTH
|DDSD_HEIGHT
|DDSD_PIXELFORMAT
;
262 ddsd
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
| (fStatic
? DDSCAPS_SYSTEMMEMORY
: 0);
263 ddsd
.ddsCaps
.dwCaps2
= fStatic
? 0 : (DDSCAPS2_TEXTUREMANAGE
|DDSCAPS2_HINTSTATIC
);
264 ddsd
.dwWidth
= m_maxsize
.cx
;
265 ddsd
.dwHeight
= m_maxsize
.cy
;
266 ddsd
.ddpfPixelFormat
.dwSize
= sizeof(DDPIXELFORMAT
);
267 ddsd
.ddpfPixelFormat
.dwFlags
= DDPF_RGB
|DDPF_ALPHAPIXELS
;
268 ddsd
.ddpfPixelFormat
.dwRGBBitCount
= 32;
269 ddsd
.ddpfPixelFormat
.dwRGBAlphaBitMask
= 0xFF000000;
270 ddsd
.ddpfPixelFormat
.dwRBitMask
= 0x00FF0000;
271 ddsd
.ddpfPixelFormat
.dwGBitMask
= 0x0000FF00;
272 ddsd
.ddpfPixelFormat
.dwBBitMask
= 0x000000FF;
274 if(m_fPow2Textures
) {
275 ddsd
.dwWidth
= ddsd
.dwHeight
= 1;
276 while(ddsd
.dwWidth
< (DWORD
)m_maxsize
.cx
) {
279 while(ddsd
.dwHeight
< (DWORD
)m_maxsize
.cy
) {
285 CComPtr
<IDirect3D7
> pD3D
;
286 CComQIPtr
<IDirectDraw7
, &IID_IDirectDraw7
> pDD
;
287 if(FAILED(m_pD3DDev
->GetDirect3D(&pD3D
)) || !pD3D
|| !(pDD
= pD3D
)) {
291 CComPtr
<IDirectDrawSurface7
> pSurface
;
292 if(FAILED(pDD
->CreateSurface(&ddsd
, &pSurface
, NULL
))) {
296 *ppSubPic
= DEBUG_NEW
CDX7SubPic(m_pD3DDev
, pSurface
);
301 (*ppSubPic
)->AddRef();