- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# DX7SubPic.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "stdafx.h"
    00023 #include <ddraw.h>
    00024 #include <d3d.h>
    00025 #include "DX7SubPic.h"
    00026
    00027 //
    00028 // CDX7SubPic
    00029 //
    00030
    00031 CDX7SubPic::CDX7SubPic(IDirect3DDevice7* pD3DDev, IDirectDrawSurface7* pSurface)
    00032         : m_pSurface(pSurface)
    00033         , m_pD3DDev(pD3DDev)
    00034 {
    00035         DDSURFACEDESC2 ddsd;
    00036         INITDDSTRUCT(ddsd);
    00037         if(SUCCEEDED(m_pSurface->GetSurfaceDesc(&ddsd)))
    00038         {
    00039                 m_maxsize.SetSize(ddsd.dwWidth, ddsd.dwHeight);
    00040                 m_rcDirty.SetRect(0, 0, ddsd.dwWidth, ddsd.dwHeight);
    00041         }
    00042 }
    00043
    00044 // ISubPic
    00045
    00046 STDMETHODIMP_(void*) CDX7SubPic::GetObject()
    00047 {
    00048         return (void*)(IDirectDrawSurface7*)m_pSurface;
    00049 }
    00050
    00051 STDMETHODIMP CDX7SubPic::GetDesc(SubPicDesc& spd)
    00052 {
    00053         DDSURFACEDESC2 ddsd;
    00054         INITDDSTRUCT(ddsd);
    00055         if(FAILED(m_pSurface->GetSurfaceDesc(&ddsd)))
    00056                 return E_FAIL;
    00057
    00058         spd.type = 0;
    00059         spd.w = m_size.cx;
    00060         spd.h = m_size.cy;
    00061         spd.bpp = (WORD)ddsd.ddpfPixelFormat.dwRGBBitCount;
    00062         spd.pitch = ddsd.lPitch;
    00063         spd.bits = ddsd.lpSurface; // should be NULL
    00064         spd.vidrect = m_vidrect;
    00065
    00066         return S_OK;
    00067 }
    00068
    00069 STDMETHODIMP CDX7SubPic::CopyTo(ISubPic* pSubPic)
    00070 {
    00071         HRESULT hr;
    00072         if(FAILED(hr = __super::CopyTo(pSubPic)))
    00073                 return hr;
    00074
    00075         CPoint p = m_rcDirty.TopLeft();
    00076         hr = m_pD3DDev->Load((IDirectDrawSurface7*)pSubPic->GetObject(), &p, (IDirectDrawSurface7*)GetObject(), m_rcDirty, 0);
    00077
    00078         return SUCCEEDED(hr) ? S_OK : E_FAIL;
    00079 }
    00080
    00081 STDMETHODIMP CDX7SubPic::ClearDirtyRect(DWORD color)
    00082 {
    00083         if(m_rcDirty.IsRectEmpty())
    00084                 return S_FALSE;
    00085
    00086         DDBLTFX fx;
    00087         INITDDSTRUCT(fx);
    00088         fx.dwFillColor = color;
    00089         m_pSurface->Blt(&m_rcDirty, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
    00090
    00091         m_rcDirty.SetRectEmpty();
    00092
    00093         return S_OK;
    00094 }
    00095
    00096 STDMETHODIMP CDX7SubPic::Lock(SubPicDesc& spd)
    00097 {
    00098         DDSURFACEDESC2 ddsd;
    00099         INITDDSTRUCT(ddsd);
    00100         if(FAILED(m_pSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL)))
    00101                 return E_FAIL;
    00102
    00103         spd.type = 0;
    00104         spd.w = m_size.cx;
    00105         spd.h = m_size.cy;
    00106         spd.bpp = (WORD)ddsd.ddpfPixelFormat.dwRGBBitCount;
    00107         spd.pitch = ddsd.lPitch;
    00108         spd.bits = ddsd.lpSurface;
    00109         spd.vidrect = m_vidrect;
    00110
    00111         return S_OK;
    00112 }
    00113
    00114 STDMETHODIMP CDX7SubPic::Unlock(RECT* pDirtyRect)
    00115 {
    00116         m_pSurface->Unlock(NULL);
    00117
    00118         if(pDirtyRect)
    00119         {
    00120                 m_rcDirty = *pDirtyRect;
    00121                 m_rcDirty.InflateRect(1, 1);
    00122                 m_rcDirty &= CRect(CPoint(0, 0), m_size);
    00123         }
    00124         else
    00125         {
    00126                 m_rcDirty = CRect(CPoint(0, 0), m_size);
    00127         }
    00128
    00129         return S_OK;
    00130 }
    00131
    00132 STDMETHODIMP CDX7SubPic::AlphaBlt(RECT* pSrc, RECT* pDst, SubPicDesc* pTarget)
    00133 {
    00134         ASSERT(pTarget == NULL);
    00135
    00136         if(!m_pD3DDev || !m_pSurface || !pSrc || !pDst)
    00137                 return E_POINTER;
    00138
    00139         CRect src(*pSrc), dst(*pDst);
    00140
    00141         HRESULT hr;
    00142
    00143     do
    00144         {
    00145                 DDSURFACEDESC2 ddsd;
    00146                 INITDDSTRUCT(ddsd);
    00147                 if(FAILED(hr = m_pSurface->GetSurfaceDesc(&ddsd)))
    00148                         break;
    00149
    00150         float w = (float)ddsd.dwWidth;
    00151         float h = (float)ddsd.dwHeight;
    00152
    00153                 struct
    00154                 {
    00155                         float x, y, z, rhw;
    00156                         float tu, tv;
    00157                 }
    00158                 pVertices[] =
    00159                 {
    00160                         {(float)dst.left, (float)dst.top, 0.5f, 2.0f, (float)src.left / w, (float)src.top / h},
    00161                         {(float)dst.right, (float)dst.top, 0.5f, 2.0f, (float)src.right / w, (float)src.top / h},
    00162                         {(float)dst.left, (float)dst.bottom, 0.5f, 2.0f, (float)src.left / w, (float)src.bottom / h},
    00163                         {(float)dst.right, (float)dst.bottom, 0.5f, 2.0f, (float)src.right / w, (float)src.bottom / h},
    00164                 };
    00165 /*
    00166                 for(int i = 0; i < countof(pVertices); i++)
    00167                 {
    00168                         pVertices[i].x -= 0.5;
    00169                         pVertices[i].y -= 0.5;
    00170                 }
    00171 */
    00172         hr = m_pD3DDev->SetTexture(0, m_pSurface);
    00173
    00174         m_pD3DDev->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
    00175         m_pD3DDev->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE);
    00176         m_pD3DDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE);
    00177         m_pD3DDev->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE); // pre-multiplied src and ...
    00178         m_pD3DDev->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCALPHA); // ... inverse alpha channel for dst
    00179
    00180                 m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
    00181         m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    00182         m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
    00183
    00184         m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
    00185         m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
    00186         m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
    00187
    00188         m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
    00189
    00190                 /*//
    00191
    00192                 D3DDEVICEDESC7 d3ddevdesc;
    00193                 m_pD3DDev->GetCaps(&d3ddevdesc);
    00194                 if(d3ddevdesc.dpcTriCaps.dwAlphaCmpCaps & D3DPCMPCAPS_LESS)
    00195                 {
    00196                         m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)0x000000FE);
    00197                         m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
    00198                         m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DPCMPCAPS_LESS);
    00199                 }
    00200
    00201         *///
    00202
    00203         if(FAILED(hr = m_pD3DDev->BeginScene()))
    00204                         break;
    00205
    00206                 hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP,
    00207                                                                                 D3DFVF_XYZRHW | D3DFVF_TEX1,
    00208                                                                                 pVertices, 4, D3DDP_WAIT);
    00209                 m_pD3DDev->EndScene();
    00210
    00211         //
    00212
    00213                 m_pD3DDev->SetTexture(0, NULL);
    00214
    00215                 return S_OK;
    00216     }
    00217         while(0);
    00218
    00219     return E_FAIL;
    00220 }
    00221
    00222 //
    00223 // CDX7SubPicAllocator
    00224 //
    00225
    00226 CDX7SubPicAllocator::CDX7SubPicAllocator(IDirect3DDevice7* pD3DDev, SIZE maxsize, bool fPow2Textures)
    00227         : ISubPicAllocatorImpl(maxsize, true, fPow2Textures)
    00228         , m_pD3DDev(pD3DDev)
    00229         , m_maxsize(maxsize)
    00230 {
    00231 }
    00232
    00233 // ISubPicAllocator
    00234
    00235 STDMETHODIMP CDX7SubPicAllocator::ChangeDevice(IUnknown* pDev)
    00236 {
    00237         CComQIPtr<IDirect3DDevice7, &IID_IDirect3DDevice7> pD3DDev = pDev;
    00238         if(!pD3DDev) return E_NOINTERFACE;
    00239
    00240         CAutoLock cAutoLock(this);
    00241         m_pD3DDev = pD3DDev;
    00242
    00243         return __super::ChangeDevice(pDev);
    00244 }
    00245
    00246 // ISubPicAllocatorImpl
    00247
    00248 bool CDX7SubPicAllocator::Alloc(bool fStatic, ISubPic** ppSubPic)
    00249 {
    00250         if(!ppSubPic)
    00251                 return(false);
    00252
    00253         CAutoLock cAutoLock(this);
    00254
    00255         DDSURFACEDESC2 ddsd;
    00256         INITDDSTRUCT(ddsd);
    00257         ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
    00258         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | (fStatic ? DDSCAPS_SYSTEMMEMORY : 0);
    00259         ddsd.ddsCaps.dwCaps2 = fStatic ? 0 : (DDSCAPS2_TEXTUREMANAGE|DDSCAPS2_HINTSTATIC);
    00260         ddsd.dwWidth = m_maxsize.cx;
    00261         ddsd.dwHeight = m_maxsize.cy;
    00262         ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
    00263         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_ALPHAPIXELS;
    00264         ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
    00265         ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
    00266         ddsd.ddpfPixelFormat.dwRBitMask        = 0x00FF0000;
    00267         ddsd.ddpfPixelFormat.dwGBitMask        = 0x0000FF00;
    00268         ddsd.ddpfPixelFormat.dwBBitMask        = 0x000000FF;
    00269
    00270         if(m_fPow2Textures)
    00271         {
    00272                 ddsd.dwWidth = ddsd.dwHeight = 1;
    00273                 while(ddsd.dwWidth < m_maxsize.cx) ddsd.dwWidth <<= 1;
    00274                 while(ddsd.dwHeight < m_maxsize.cy) ddsd.dwHeight <<= 1;
    00275         }
    00276
    00277
    00278         CComPtr<IDirect3D7> pD3D;
    00279         CComQIPtr<IDirectDraw7, &IID_IDirectDraw7> pDD;
    00280         if(FAILED(m_pD3DDev->GetDirect3D(&pD3D)) || !pD3D || !(pDD = pD3D))
    00281                 return(false);
    00282
    00283         CComPtr<IDirectDrawSurface7> pSurface;
    00284         if(FAILED(pDD->CreateSurface(&ddsd, &pSurface, NULL)))
    00285                 return(false);
    00286
    00287         if(!(*ppSubPic = new CDX7SubPic(m_pD3DDev, pSurface)))
    00288                 return(false);
    00289
    00290         (*ppSubPic)->AddRef();
    00291
    00292         return(true);
    00293 }