- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# DX9SubPic.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 <d3d9.h>
    00024 #include <Vmr9.h>
    00025 #include "DX9SubPic.h"
    00026
    00027 //
    00028 // CDX9SubPic
    00029 //
    00030
    00031 CDX9SubPic::CDX9SubPic(IDirect3DSurface9* pSurface)
    00032         : m_pSurface(pSurface)
    00033 {
    00034         D3DSURFACE_DESC d3dsd;
    00035         ZeroMemory(&d3dsd, sizeof(d3dsd));
    00036         if(SUCCEEDED(m_pSurface->GetDesc(&d3dsd)))
    00037         {
    00038                 m_maxsize.SetSize(d3dsd.Width, d3dsd.Height);
    00039                 m_rcDirty.SetRect(0, 0, d3dsd.Width, d3dsd.Height);
    00040         }
    00041 }
    00042
    00043 // ISubPic
    00044
    00045 STDMETHODIMP_(void*) CDX9SubPic::GetObject()
    00046 {
    00047         CComPtr<IDirect3DTexture9> pTexture;
    00048         if(SUCCEEDED(m_pSurface->GetContainer(IID_IDirect3DTexture9, (void**)&pTexture)))
    00049                 return (void*)(IDirect3DTexture9*)pTexture;
    00050
    00051         return NULL;
    00052 }
    00053
    00054 STDMETHODIMP CDX9SubPic::GetDesc(SubPicDesc& spd)
    00055 {
    00056         D3DSURFACE_DESC d3dsd;
    00057         ZeroMemory(&d3dsd, sizeof(d3dsd));
    00058         if(FAILED(m_pSurface->GetDesc(&d3dsd)))
    00059                 return E_FAIL;
    00060
    00061         spd.type = 0;
    00062         spd.w = m_size.cx;
    00063         spd.h = m_size.cy;
    00064         spd.bpp =
    00065                 d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 :
    00066                 d3dsd.Format == D3DFMT_A4R4G4B4 ? 16 : 0;
    00067         spd.pitch = 0;
    00068         spd.bits = NULL;
    00069         spd.vidrect = m_vidrect;
    00070
    00071         return S_OK;
    00072 }
    00073
    00074 STDMETHODIMP CDX9SubPic::CopyTo(ISubPic* pSubPic)
    00075 {
    00076         HRESULT hr;
    00077         if(FAILED(hr = __super::CopyTo(pSubPic)))
    00078                 return hr;
    00079
    00080         if(m_rcDirty.IsRectEmpty())
    00081                 return S_FALSE;
    00082
    00083         CComPtr<IDirect3DDevice9> pD3DDev;
    00084         if(!m_pSurface || FAILED(m_pSurface->GetDevice(&pD3DDev)) || !pD3DDev)
    00085                 return E_FAIL;
    00086
    00087         hr = pD3DDev->UpdateTexture((IDirect3DTexture9*)GetObject(), (IDirect3DTexture9*)pSubPic->GetObject());
    00088
    00089         return SUCCEEDED(hr) ? S_OK : E_FAIL;
    00090 }
    00091
    00092 STDMETHODIMP CDX9SubPic::ClearDirtyRect(DWORD color)
    00093 {
    00094         if(m_rcDirty.IsRectEmpty())
    00095                 return S_FALSE;
    00096
    00097         CComPtr<IDirect3DDevice9> pD3DDev;
    00098         if(!m_pSurface || FAILED(m_pSurface->GetDevice(&pD3DDev)) || !pD3DDev)
    00099                 return E_FAIL;
    00100
    00101         SubPicDesc spd;
    00102         if(SUCCEEDED(Lock(spd)))
    00103         {
    00104                 int h = m_rcDirty.Height();
    00105
    00106                 BYTE* ptr = (BYTE*)spd.bits + spd.pitch*m_rcDirty.top + (m_rcDirty.left*spd.bpp>>3);
    00107
    00108                 if(spd.bpp == 16)
    00109                 {
    00110                         while(h-- > 0)
    00111                         {
    00112                                 WORD* start = (WORD*)ptr;
    00113                                 WORD* end = start + m_rcDirty.Width();
    00114                                 while(start < end) *start++ = (WORD)color;
    00115                                 ptr += spd.pitch;
    00116                         }
    00117                 }
    00118                 else if(spd.bpp == 32)
    00119                 {
    00120                         while(h-- > 0)
    00121                         {
    00122                                 DWORD* start = (DWORD*)ptr;
    00123                                 DWORD* end = start + m_rcDirty.Width();
    00124                                 while(start < end) *start++ = color;
    00125                                 ptr += spd.pitch;
    00126                         }
    00127                 }
    00128 /*
    00129                 DWORD* ptr = (DWORD*)bm.bits;
    00130                 DWORD* end = ptr + bm.h*bm.wBytes/4;
    00131                 while(ptr < end) *ptr++ = color;
    00132 */
    00133                 Unlock(NULL);
    00134         }
    00135
    00136 //              HRESULT hr = pD3DDev->ColorFill(m_pSurface, m_rcDirty, color);
    00137
    00138         m_rcDirty.SetRectEmpty();
    00139
    00140         return S_OK;
    00141 }
    00142
    00143 STDMETHODIMP CDX9SubPic::Lock(SubPicDesc& spd)
    00144 {
    00145         D3DSURFACE_DESC d3dsd;
    00146         ZeroMemory(&d3dsd, sizeof(d3dsd));
    00147         if(FAILED(m_pSurface->GetDesc(&d3dsd)))
    00148                 return E_FAIL;
    00149
    00150         D3DLOCKED_RECT LockedRect;
    00151         ZeroMemory(&LockedRect, sizeof(LockedRect));
    00152         if(FAILED(m_pSurface->LockRect(&LockedRect, NULL, 0)))
    00153                 return E_FAIL;
    00154
    00155         spd.type = 0;
    00156         spd.w = m_size.cx;
    00157         spd.h = m_size.cy;
    00158         spd.bpp =
    00159                 d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 :
    00160                 d3dsd.Format == D3DFMT_A4R4G4B4 ? 16 : 0;
    00161         spd.pitch = LockedRect.Pitch;
    00162         spd.bits = LockedRect.pBits;
    00163         spd.vidrect = m_vidrect;
    00164
    00165         return S_OK;
    00166 }
    00167
    00168 STDMETHODIMP CDX9SubPic::Unlock(RECT* pDirtyRect)
    00169 {
    00170         m_pSurface->UnlockRect();
    00171
    00172         if(pDirtyRect)
    00173         {
    00174                 m_rcDirty = *pDirtyRect;
    00175                 m_rcDirty.InflateRect(1, 1);
    00176                 m_rcDirty &= CRect(CPoint(0, 0), m_size);
    00177         }
    00178         else
    00179         {
    00180                 m_rcDirty = CRect(CPoint(0, 0), m_size);
    00181         }
    00182
    00183         return S_OK;
    00184 }
    00185
    00186 STDMETHODIMP CDX9SubPic::AlphaBlt(RECT* pSrc, RECT* pDst, SubPicDesc* pTarget)
    00187 {
    00188         ASSERT(pTarget == NULL);
    00189
    00190         if(!pSrc || !pDst)
    00191                 return E_POINTER;
    00192
    00193         CRect src(*pSrc), dst(*pDst);
    00194
    00195         CComPtr<IDirect3DDevice9> pD3DDev;
    00196         CComPtr<IDirect3DTexture9> pTexture = (IDirect3DTexture9*)GetObject();
    00197         if(!pTexture || FAILED(pTexture->GetDevice(&pD3DDev)) || !pD3DDev)
    00198                 return E_NOINTERFACE;
    00199
    00200         HRESULT hr;
    00201
    00202     do
    00203         {
    00204                 D3DSURFACE_DESC d3dsd;
    00205                 ZeroMemory(&d3dsd, sizeof(d3dsd));
    00206                 if(FAILED(pTexture->GetLevelDesc(0, &d3dsd)) /*|| d3dsd.Type != D3DRTYPE_TEXTURE*/)
    00207                         break;
    00208
    00209         float w = (float)d3dsd.Width;
    00210         float h = (float)d3dsd.Height;
    00211
    00212                 struct
    00213                 {
    00214                         float x, y, z, rhw;
    00215                         float tu, tv;
    00216                 }
    00217                 pVertices[] =
    00218                 {
    00219                         {(float)dst.left, (float)dst.top, 0.5f, 2.0f, (float)src.left / w, (float)src.top / h},
    00220                         {(float)dst.right, (float)dst.top, 0.5f, 2.0f, (float)src.right / w, (float)src.top / h},
    00221                         {(float)dst.left, (float)dst.bottom, 0.5f, 2.0f, (float)src.left / w, (float)src.bottom / h},
    00222                         {(float)dst.right, (float)dst.bottom, 0.5f, 2.0f, (float)src.right / w, (float)src.bottom / h},
    00223                 };
    00224 /*
    00225                 for(int i = 0; i < countof(pVertices); i++)
    00226                 {
    00227                         pVertices[i].x -= 0.5;
    00228                         pVertices[i].y -= 0.5;
    00229                 }
    00230 */
    00231         hr = pD3DDev->SetTexture(0, pTexture);
    00232
    00233         hr = pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    00234         hr = pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
    00235                 hr = pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
    00236         hr = pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    00237         hr = pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); // pre-multiplied src and ...
    00238         hr = pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA); // ... inverse alpha channel for dst
    00239
    00240                 hr = pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
    00241         hr = pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    00242         hr = pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
    00243
    00244         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    00245         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
    00246         hr = pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
    00247
    00248                 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
    00249                 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
    00250
    00251                 /*//
    00252
    00253                 D3DCAPS9 d3dcaps9;
    00254                 hr = pD3DDev->GetDeviceCaps(&d3dcaps9);
    00255                 if(d3dcaps9.AlphaCmpCaps & D3DPCMPCAPS_LESS)
    00256                 {
    00257                         hr = pD3DDev->SetRenderState(D3DRS_ALPHAREF, (DWORD)0x000000FE);
    00258                         hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
    00259                         hr = pD3DDev->SetRenderState(D3DRS_ALPHAFUNC, D3DPCMPCAPS_LESS);
    00260                 }
    00261
    00262                 *///
    00263
    00264                 if(FAILED(hr = pD3DDev->BeginScene()))
    00265                         break;
    00266
    00267         hr = pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
    00268                 hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
    00269
    00270                 hr = pD3DDev->EndScene();
    00271
    00272         //
    00273
    00274                 pD3DDev->SetTexture(0, NULL);
    00275
    00276                 return S_OK;
    00277     }
    00278         while(0);
    00279
    00280     return E_FAIL;
    00281 }
    00282
    00283 //
    00284 // CDX9SubPicAllocator
    00285 //
    00286
    00287 CDX9SubPicAllocator::CDX9SubPicAllocator(IDirect3DDevice9* pD3DDev, SIZE maxsize, bool fPow2Textures)
    00288         : ISubPicAllocatorImpl(maxsize, true, fPow2Textures)
    00289         , m_pD3DDev(pD3DDev)
    00290         , m_maxsize(maxsize)
    00291 {
    00292         m_pD3DDev = pD3DDev;
    00293         m_maxsize = maxsize;
    00294 }
    00295
    00296 // ISubPicAllocator
    00297
    00298 STDMETHODIMP CDX9SubPicAllocator::ChangeDevice(IUnknown* pDev)
    00299 {
    00300         CComQIPtr<IDirect3DDevice9> pD3DDev = pDev;
    00301         if(!pD3DDev) return E_NOINTERFACE;
    00302
    00303         CAutoLock cAutoLock(this);
    00304         m_pD3DDev = pD3DDev;
    00305
    00306         return __super::ChangeDevice(pDev);
    00307 }
    00308
    00309 // ISubPicAllocatorImpl
    00310
    00311 bool CDX9SubPicAllocator::Alloc(bool fStatic, ISubPic** ppSubPic)
    00312 {
    00313         if(!ppSubPic)
    00314                 return(false);
    00315
    00316         CAutoLock cAutoLock(this);
    00317
    00318         *ppSubPic = NULL;
    00319
    00320         CComPtr<IDirect3DSurface9> pSurface;
    00321
    00322         int Width = m_maxsize.cx;
    00323         int Height = m_maxsize.cy;
    00324
    00325         if(m_fPow2Textures)
    00326         {
    00327                 Width = Height = 1;
    00328                 while(Width < m_maxsize.cx) Width <<= 1;
    00329                 while(Height < m_maxsize.cy) Height <<= 1;
    00330         }
    00331
    00332         CComPtr<IDirect3DTexture9> pTexture;
    00333         if(FAILED(m_pD3DDev->CreateTexture(Width, Height, 1, 0, D3DFMT_A8R8G8B8, fStatic?D3DPOOL_SYSTEMMEM:D3DPOOL_DEFAULT, &pTexture, NULL)))
    00334                 return(false);
    00335
    00336         if(FAILED(pTexture->GetSurfaceLevel(0, &pSurface)))
    00337                 return(false);
    00338
    00339         if(!(*ppSubPic = new CDX9SubPic(pSurface)))
    00340                 return(false);
    00341
    00342         (*ppSubPic)->AddRef();
    00343
    00344         return(true);
    00345 }