00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include <d3d9.h>
00024 #include <Vmr9.h>
00025 #include "DX9SubPic.h"
00026
00027
00028
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
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
00130
00131
00132
00133 Unlock(NULL);
00134 }
00135
00136
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)) )
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
00226
00227
00228
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);
00238 hr = pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA);
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
00254
00255
00256
00257
00258
00259
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
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
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
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 }