Support unrar64.dll
[xy_vsfilter.git] / src / subpic / DX7SubPic.cpp
blob38e9abeca7441c3eafa698e6a4ad0f46e9df4956
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 <ddraw.h>
24 #include <d3d.h>
25 #include "DX7SubPic.h"
28 // CDX7SubPic
31 CDX7SubPic::CDX7SubPic(IDirect3DDevice7* pD3DDev, IDirectDrawSurface7* pSurface)
32 : m_pSurface(pSurface)
33 , m_pD3DDev(pD3DDev)
35 DDSURFACEDESC2 ddsd;
36 INITDDSTRUCT(ddsd);
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);
43 // ISubPic
45 STDMETHODIMP_(void*) CDX7SubPic::GetObject() const
47 return (void*)(IDirectDrawSurface7*)m_pSurface;
50 STDMETHODIMP CDX7SubPic::GetDesc(SubPicDesc& spd) const
52 DDSURFACEDESC2 ddsd;
53 INITDDSTRUCT(ddsd);
54 if(FAILED(m_pSurface->GetSurfaceDesc(&ddsd))) {
55 return E_FAIL;
58 spd.type = 0;
59 spd.w = m_size.cx;
60 spd.h = m_size.cy;
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;
66 return S_OK;
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)
73 HRESULT hr;
74 if(FAILED(hr = __super::CopyTo(pSubPic))) {
75 return hr;
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()) {
88 return S_FALSE;
91 DDBLTFX fx;
92 INITDDSTRUCT(fx);
93 fx.dwFillColor = color;
94 m_pSurface->Blt(&m_rcDirty, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
96 m_rcDirty.SetRectEmpty();
98 return S_OK;
101 STDMETHODIMP CDX7SubPic::Lock(SubPicDesc& spd)
103 DDSURFACEDESC2 ddsd;
104 INITDDSTRUCT(ddsd);
105 if(FAILED(m_pSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL))) {
106 return E_FAIL;
109 spd.type = 0;
110 spd.w = m_size.cx;
111 spd.h = m_size.cy;
112 spd.bpp = (WORD)ddsd.ddpfPixelFormat.dwRGBBitCount;
113 spd.pitch = ddsd.lPitch;
114 spd.bits = ddsd.lpSurface;
115 spd.vidrect = m_vidrect;
117 return S_OK;
120 STDMETHODIMP CDX7SubPic::Unlock(RECT* pDirtyRect)
122 m_pSurface->Unlock(NULL);
124 if(pDirtyRect) {
125 m_rcDirty = *pDirtyRect;
126 m_rcDirty.InflateRect(1, 1);
127 m_rcDirty &= CRect(CPoint(0, 0), m_size);
128 } else {
129 m_rcDirty = CRect(CPoint(0, 0), m_size);
131 return S_OK;
134 STDMETHODIMP CDX7SubPic::AlphaBlt(const RECT* pSrc, const RECT* pDst, SubPicDesc* pTarget)
136 ASSERT(pTarget == NULL);
138 if(!m_pD3DDev || !m_pSurface || !pSrc || !pDst) {
139 return E_POINTER;
142 CRect src(*pSrc), dst(*pDst);
144 HRESULT hr;
146 do {
147 DDSURFACEDESC2 ddsd;
148 INITDDSTRUCT(ddsd);
149 if(FAILED(hr = m_pSurface->GetSurfaceDesc(&ddsd))) {
150 break;
153 float w = (float)ddsd.dwWidth;
154 float h = (float)ddsd.dwHeight;
156 struct {
157 float x, y, z, rhw;
158 float tu, tv;
160 pVertices[] = {
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);
191 /*//
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);
202 *///
204 if(FAILED(hr = m_pD3DDev->BeginScene())) {
205 break;
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);
217 return S_OK;
218 } while(0);
220 return E_FAIL;
224 // CDX7SubPicAllocator
227 CDX7SubPicAllocator::CDX7SubPicAllocator(IDirect3DDevice7* pD3DDev, SIZE maxsize, bool fPow2Textures)
228 : CSubPicAllocatorImpl(maxsize, true, fPow2Textures)
229 , m_pD3DDev(pD3DDev)
230 , m_maxsize(maxsize)
234 // ISubPicAllocator
236 STDMETHODIMP CDX7SubPicAllocator::ChangeDevice(IUnknown* pDev)
238 CComQIPtr<IDirect3DDevice7, &IID_IDirect3DDevice7> pD3DDev = pDev;
239 if(!pD3DDev) {
240 return E_NOINTERFACE;
243 CAutoLock cAutoLock(this);
244 m_pD3DDev = pD3DDev;
246 return __super::ChangeDevice(pDev);
249 // ISubPicAllocatorImpl
251 bool CDX7SubPicAllocator::Alloc(bool fStatic, ISubPic** ppSubPic)
253 if(!ppSubPic) {
254 return false;
257 CAutoLock cAutoLock(this);
259 DDSURFACEDESC2 ddsd;
260 INITDDSTRUCT(ddsd);
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) {
277 ddsd.dwWidth <<= 1;
279 while(ddsd.dwHeight < (DWORD)m_maxsize.cy) {
280 ddsd.dwHeight <<= 1;
285 CComPtr<IDirect3D7> pD3D;
286 CComQIPtr<IDirectDraw7, &IID_IDirectDraw7> pDD;
287 if(FAILED(m_pD3DDev->GetDirect3D(&pD3D)) || !pD3D || !(pDD = pD3D)) {
288 return false;
291 CComPtr<IDirectDrawSurface7> pSurface;
292 if(FAILED(pDD->CreateSurface(&ddsd, &pSurface, NULL))) {
293 return false;
296 *ppSubPic = DEBUG_NEW CDX7SubPic(m_pD3DDev, pSurface);
297 if(!(*ppSubPic)) {
298 return false;
301 (*ppSubPic)->AddRef();
303 return true;