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 }

Generated on Tue Dec 13 14:47:53 2005 for guliverkli by  doxygen 1.4.5