/*****************************Private*Routine******************************\ * OnSetDDrawDevice * \**************************************************************************/ HRESULT CMpegMovie::OnSetDDrawDevice( LPDIRECTDRAW7 pDD, HMONITOR hMon ) { HRESULT hr = S_OK; RELEASE(m_pddsRenderT); RELEASE(m_pddsPriText); RELEASE(m_pddsPrimary); __try { DDSURFACEDESC2 ddsd; // A surface description structure INITDDSTRUCT(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; CHECK_HR(hr = pDD->EnumSurfaces(DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, &ddsd, &m_pddsPrimary, DDSurfEnumFunc)); if(!m_pddsPrimary) { hr = E_FAIL; __leave; } MONITORINFOEX miInfoEx; miInfoEx.cbSize = sizeof(miInfoEx); GetMonitorInfo(hMon, &miInfoEx); INITDDSTRUCT(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = (miInfoEx.rcMonitor.right - miInfoEx.rcMonitor.left); ddsd.dwHeight = (miInfoEx.rcMonitor.bottom - miInfoEx.rcMonitor.top); CHECK_HR(hr = pDD->CreateSurface(&ddsd, &m_pddsPriText, NULL)); CHECK_HR(hr = pDD->CreateSurface(&ddsd, &m_pddsRenderT, NULL)); } __finally { if(FAILED(hr)) { RELEASE(m_pddsRenderT); RELEASE(m_pddsPriText); RELEASE(m_pddsPrimary); } } return hr; }
/*****************************Private*Routine******************************\ * DDSurfEnumFunc * \**************************************************************************/ HRESULT WINAPI DDSurfEnumFunc( LPDIRECTDRAWSURFACE7 pdds, DDSURFACEDESC2* pddsd, void* lpContext ) { LPDIRECTDRAWSURFACE7* ppdds = (LPDIRECTDRAWSURFACE7*)lpContext; DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); HRESULT hr = pdds->GetSurfaceDesc(&ddsd); if(SUCCEEDED(hr)) { if(ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { *ppdds = pdds; return DDENUMRET_CANCEL; } } pdds->Release(); return DDENUMRET_OK; }
bool CDX7SubPicAllocator::Alloc(bool fStatic, ISubPic** ppSubPic) { if (!ppSubPic) { return false; } if (m_maxsize.cx <= 0 || m_maxsize.cy <= 0) { return false; } CAutoLock cAutoLock(this); DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | (fStatic ? DDSCAPS_SYSTEMMEMORY : 0); ddsd.ddsCaps.dwCaps2 = fStatic ? 0 : (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTSTATIC); ddsd.dwWidth = m_maxsize.cx; ddsd.dwHeight = m_maxsize.cy; ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; ddsd.ddpfPixelFormat.dwRGBBitCount = 32; ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000; ddsd.ddpfPixelFormat.dwRBitMask = 0x00FF0000; ddsd.ddpfPixelFormat.dwGBitMask = 0x0000FF00; ddsd.ddpfPixelFormat.dwBBitMask = 0x000000FF; if (m_fPow2Textures && ddsd.dwWidth < 1024 && ddsd.dwHeight < 1024) { ddsd.dwWidth = ddsd.dwHeight = 1; while (ddsd.dwWidth < (DWORD)m_maxsize.cx) { ddsd.dwWidth <<= 1; } while (ddsd.dwHeight < (DWORD)m_maxsize.cy) { ddsd.dwHeight <<= 1; } } CComPtr<IDirect3D7> pD3D; CComQIPtr<IDirectDraw7, &IID_IDirectDraw7> pDD; if (FAILED(m_pD3DDev->GetDirect3D(&pD3D)) || !pD3D || !(pDD = pD3D)) { return false; } CComPtr<IDirectDrawSurface7> pSurface; if (FAILED(pDD->CreateSurface(&ddsd, &pSurface, nullptr))) { return false; } try { *ppSubPic = DEBUG_NEW CDX7SubPic(m_pD3DDev, pSurface); } catch (std::bad_alloc) { return false; } (*ppSubPic)->AddRef(); return true; }
CDX7SubPic::CDX7SubPic(IDirect3DDevice7* pD3DDev, IDirectDrawSurface7* pSurface) : m_pSurface(pSurface) , m_pD3DDev(pD3DDev) { DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); if (SUCCEEDED(m_pSurface->GetSurfaceDesc(&ddsd))) { m_maxsize.SetSize(ddsd.dwWidth, ddsd.dwHeight); m_rcDirty.SetRect(0, 0, ddsd.dwWidth, ddsd.dwHeight); } }
STDMETHODIMP CDX7SubPic::ClearDirtyRect(DWORD color) { if(m_rcDirty.IsRectEmpty()) return S_FALSE; DDBLTFX fx; INITDDSTRUCT(fx); fx.dwFillColor = color; m_pSurface->Blt(&m_rcDirty, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx); m_rcDirty.SetRectEmpty(); return S_OK; }
STDMETHODIMP CDX7SubPic::Lock(SubPicDesc& spd) { DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); if(FAILED(m_pSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL))) return E_FAIL; spd.type = 0; spd.w = m_size.cx; spd.h = m_size.cy; spd.bpp = (WORD)ddsd.ddpfPixelFormat.dwRGBBitCount; spd.pitch = ddsd.lPitch; spd.bits = ddsd.lpSurface; spd.vidrect = m_vidrect; return S_OK; }
STDMETHODIMP CDX7SubPic::GetDesc(SubPicDesc& spd) { DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); if(FAILED(m_pSurface->GetSurfaceDesc(&ddsd))) return E_FAIL; spd.type = 0; spd.w = m_size.cx; spd.h = m_size.cy; spd.bpp = (WORD)ddsd.ddpfPixelFormat.dwRGBBitCount; spd.pitch = ddsd.lPitch; spd.bits = ddsd.lpSurface; // should be NULL spd.vidrect = m_vidrect; return S_OK; }
bool CDX7SubPicAllocator::Alloc(bool fStatic, ISubPic** ppSubPic) { if (!ppSubPic) { return false; } CAutoLock cAutoLock(this); DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | (fStatic ? DDSCAPS_SYSTEMMEMORY : 0); ddsd.ddsCaps.dwCaps2 = fStatic ? 0 : (DDSCAPS2_TEXTUREMANAGE|DDSCAPS2_HINTSTATIC); ddsd.dwWidth = m_maxsize.cx; ddsd.dwHeight = m_maxsize.cy; ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB|DDPF_ALPHAPIXELS; ddsd.ddpfPixelFormat.dwRGBBitCount = 32; ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000; ddsd.ddpfPixelFormat.dwRBitMask = 0x00FF0000; ddsd.ddpfPixelFormat.dwGBitMask = 0x0000FF00; ddsd.ddpfPixelFormat.dwBBitMask = 0x000000FF; CComPtr<IDirect3D7> pD3D; CComQIPtr<IDirectDraw7, &IID_IDirectDraw7> pDD; if (FAILED(m_pD3DDev->GetDirect3D(&pD3D)) || !pD3D || !(pDD = pD3D)) { return false; } CComPtr<IDirectDrawSurface7> pSurface; if (FAILED(pDD->CreateSurface(&ddsd, &pSurface, NULL))) { return false; } *ppSubPic = DNew CDX7SubPic(m_pD3DDev, pSurface); if (!(*ppSubPic)) { return false; } (*ppSubPic)->AddRef(); return true; }
//---------------------------------------------------------------------------- // PresentImage // // Here all the fun happens. lpPresInfo contains surface with current video image // Call m_AlphaBlt->AlphaBlt to perform all the necessary transformation //---------------------------------------------------------------------------- STDMETHODIMP CMpegMovie::PresentImage( DWORD_PTR dwUserID, VMRPRESENTATIONINFO* lpPresInfo ) { // clear the background DDBLTFX ddFX; INITDDSTRUCT(ddFX); RECT rcS = {0, 0, 640, 480}; RECT rcD = {128, 96, 512, 384}; RECT rcDt ={128, 0, 512, 288}; m_lpDefWC->GetVideoPosition(&rcS, NULL); if( g_ss.bShowTwist ) { m_AlphaBlt->AlphaBlt(&rcDt, lpPresInfo->lpSurf, &rcS, 0xFF); } else { m_AlphaBlt->AlphaBlt(&rcD, lpPresInfo->lpSurf, &rcS, 0xFF); } m_lpSurf->Flip(NULL,0); if( g_ss.bShowStatistics && m_Qp) { // call IQualProp functions here to get performance statistics GetPerformance(); } // Show the scene m_pDDObject.GetFB()->Flip(NULL, /*DDFLIP_WAIT*/ 0); return S_OK; }
STDMETHODIMP CDX7SubPic::AlphaBlt(RECT* pSrc, RECT* pDst, SubPicDesc* pTarget) { ASSERT(pTarget == NULL); if (!m_pD3DDev || !m_pSurface || !pSrc || !pDst) { return E_POINTER; } CRect src(*pSrc), dst(*pDst); HRESULT hr; do { DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); if (FAILED(hr = m_pSurface->GetSurfaceDesc(&ddsd))) { break; } float w = (float)ddsd.dwWidth; float h = (float)ddsd.dwHeight; struct { float x, y, z, rhw; float tu, tv; } pVertices[] = { {(float)dst.left, (float)dst.top, 0.5f, 2.0f, (float)src.left / w, (float)src.top / h}, {(float)dst.right, (float)dst.top, 0.5f, 2.0f, (float)src.right / w, (float)src.top / h}, {(float)dst.left, (float)dst.bottom, 0.5f, 2.0f, (float)src.left / w, (float)src.bottom / h}, {(float)dst.right, (float)dst.bottom, 0.5f, 2.0f, (float)src.right / w, (float)src.bottom / h}, }; /* for(ptrdiff_t i = 0; i < countof(pVertices); i++) { pVertices[i].x -= 0.5; pVertices[i].y -= 0.5; } */ hr = m_pD3DDev->SetTexture(0, m_pSurface); m_pD3DDev->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE); // pre-multiplied src and ... m_pD3DDev->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCALPHA); // ... inverse alpha channel for dst m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR); m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR); m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); /*// D3DDEVICEDESC7 d3ddevdesc; m_pD3DDev->GetCaps(&d3ddevdesc); if(d3ddevdesc.dpcTriCaps.dwAlphaCmpCaps & D3DPCMPCAPS_LESS) { m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)0x000000FE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DPCMPCAPS_LESS); } */// if (FAILED(hr = m_pD3DDev->BeginScene())) { break; } hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, pVertices, 4, D3DDP_WAIT); m_pD3DDev->EndScene(); // m_pD3DDev->SetTexture(0, NULL); return S_OK; } while (0); return E_FAIL; }
//----------------------------------------------------------------------------- // Name: InitDeviceObjects() // Desc: Initializes device-dependent objects, including the vertex buffer used // for rendering text and the texture map which stores the font image. //----------------------------------------------------------------------------- HRESULT CD3DFont::InitDeviceObjects( LPDIRECTDRAW7 pDD, LPDIRECT3DDEVICE7 pd3dDevice ) { HRESULT hr; // Keep a local copy of the device m_pd3dDevice = pd3dDevice; typedef enum FontFormats { eNull, eX4R4G4B4, eR5G6B5, eX8R8G8B8, }FontFormats; FontFormats fmt = eNull; // Establish the font and texture size m_fTextScale = 1.0f; // Draw fonts into texture without scaling // Large fonts need larger textures if( m_dwFontHeight > 40 ) m_dwTexWidth = m_dwTexHeight = 1024; else if( m_dwFontHeight > 20 ) m_dwTexWidth = m_dwTexHeight = 512; else m_dwTexWidth = m_dwTexHeight = 256; // If requested texture is too big, use a smaller texture and smaller font, // and scale up when rendering. D3DDEVICEDESC7 d3dCaps; m_pd3dDevice->GetCaps( &d3dCaps ); if( m_dwTexWidth > d3dCaps.dwMaxTextureWidth ) { m_fTextScale = (FLOAT)d3dCaps.dwMaxTextureWidth / (FLOAT)m_dwTexWidth; m_dwTexWidth = m_dwTexHeight = d3dCaps.dwMaxTextureWidth; } DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTSTATIC; ddsd.dwWidth = m_dwTexWidth; ddsd.dwHeight = m_dwTexHeight; IDirectDrawSurface7 * pRT = NULL; hr = m_pd3dDevice->GetRenderTarget( &pRT ); if( SUCCEEDED(hr) && pRT ) { DDSURFACEDESC2 ddsd_rt; INITDDSTRUCT(ddsd_rt); ddsd_rt.dwFlags = DDSD_PIXELFORMAT; hr = pRT->GetSurfaceDesc( &ddsd_rt ); if( SUCCEEDED( hr )) { memcpy( (LPVOID)&(ddsd.ddpfPixelFormat), (LPVOID)&(ddsd_rt.ddpfPixelFormat), sizeof( DDPIXELFORMAT)); } if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32) { fmt = eX8R8G8B8; } else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 ) { if( ddsd.ddpfPixelFormat.dwRBitMask == 0xF000 && ddsd.ddpfPixelFormat.dwGBitMask == 0x00F0 && ddsd.ddpfPixelFormat.dwBBitMask == 0x000F) { fmt = eX4R4G4B4; } else if ( ddsd.ddpfPixelFormat.dwRBitMask == 0xF800 && ddsd.ddpfPixelFormat.dwGBitMask == 0x7E0 && ddsd.ddpfPixelFormat.dwBBitMask == 0x1F ) { fmt = eR5G6B5; } } } if(FAILED(hr)) { ddsd.ddpfPixelFormat.dwFourCC = BI_RGB; ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; ddsd.ddpfPixelFormat.dwRGBBitCount = 16; ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xF000; ddsd.ddpfPixelFormat.dwRBitMask = 0x0F00; ddsd.ddpfPixelFormat.dwGBitMask = 0x00F0; ddsd.ddpfPixelFormat.dwBBitMask = 0x000F; fmt = eX4R4G4B4; } if( pRT ) { pRT->Release(); pRT = NULL; } // Create a new texture for the font hr = pDD->CreateSurface(&ddsd, &m_pTexture, NULL); if( FAILED(hr) ) return hr; // Prepare to create a bitmap DWORD * pBitmapBits; BITMAPINFO bmi; ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = (int)m_dwTexWidth; bmi.bmiHeader.biHeight = -(int)m_dwTexHeight; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biBitCount = 32; // Create a DC and a bitmap for the font HDC hDC = CreateCompatibleDC( NULL ); if( NULL == hDC ) return E_FAIL; HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (VOID**)&pBitmapBits, NULL, 0 ); SetMapMode( hDC, MM_TEXT ); // Create a font. By specifying ANTIALIASED_QUALITY, we might get an // antialiased font, but this is not guaranteed. INT nHeight = -MulDiv( m_dwFontHeight, (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 ); DWORD dwBold = (m_dwFontFlags&D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL; DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE : FALSE; HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic, FALSE, FALSE, DEFAULT_CHARSET, OUT_STRING_PRECIS, CLIP_STROKE_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, m_strFontName ); if( NULL==hFont ) return E_FAIL; SelectObject( hDC, hbmBitmap ); SelectObject( hDC, hFont ); // Set text properties SetTextColor( hDC, RGB(255,255,255) ); SetBkColor( hDC, 0x00000000 ); SetTextAlign( hDC, TA_TOP ); // Loop through all printable character and output them to the bitmap.. // Meanwhile, keep track of the corresponding tex coords for each character. DWORD x = 0; DWORD y = 0; TCHAR str[2] = _T("x"); SIZE size; for( TCHAR c=32; c<127; c++ ) { str[0] = c; GetTextExtentPoint32( hDC, str, 1, &size ); if( (DWORD)(x+size.cx+1) > m_dwTexWidth ) { x = 0; y += size.cy+1; } ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL ); m_fTexCoords[c-32][0] = ((FLOAT)(x+0))/m_dwTexWidth; m_fTexCoords[c-32][1] = ((FLOAT)(y+0))/m_dwTexHeight; m_fTexCoords[c-32][2] = ((FLOAT)(x+0+size.cx))/m_dwTexWidth; m_fTexCoords[c-32][3] = ((FLOAT)(y+0+size.cy))/m_dwTexHeight; x += size.cx+1; } if( fmt == eNull ) { OutputDebugString( TEXT("\n*** WARNING: This sample shows text only in one of the following formats: X8R8G8B8, X4R4G4B4, or R5G6B5. Text functions are DISABLED\n")); } // Lock the surface and write the alpha values for the set pixels m_pTexture->Lock(NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL); switch( fmt ) { case eX4R4G4B4: { WORD* pDst16 = (WORD*)ddsd.lpSurface; BYTE bAlpha; // 4-bit measure of pixel intensity for( y=0; y < m_dwTexHeight; y++ ) { for( x=0; x < m_dwTexWidth; x++ ) { bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4); if (bAlpha > 0) { *pDst16++ = (WORD) ((bAlpha << 12) | 0x0fff); } else { *pDst16++ = 0x0000; } } } } break; case eX8R8G8B8: { DWORD* pDst32 = (DWORD*)ddsd.lpSurface; BYTE bAlpha; // 4-bit measure of pixel intensity for( y=0; y < m_dwTexHeight; y++ ) { for( x=0; x < m_dwTexWidth; x++ ) { bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff)); if (bAlpha > 0) { *pDst32++ = (DWORD) ((bAlpha << 24) | 0x00ffffff); } else { *pDst32++ = 0x0000; } } } } break; case eR5G6B5: { WORD* pDst16 = (WORD*)ddsd.lpSurface; BYTE bAlpha; // 4-bit measure of pixel intensity for( y=0; y < m_dwTexHeight; y++ ) { for( x=0; x < m_dwTexWidth; x++ ) { bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 3); if (bAlpha > 0) { *pDst16++ = (WORD) ((bAlpha << 11) | (bAlpha << 6) | bAlpha); } else { *pDst16++ = 0x0000; } } } } }// switch // Done updating texture, so clean up used objects m_pTexture->Unlock(NULL); DeleteObject( hbmBitmap ); DeleteDC( hDC ); DeleteObject( hFont ); return S_OK; }
//------------------------------------------------------------------------- // InitializeEnvironment // creates default allocator-presenter and sets D3D environment //------------------------------------------------------------------------- HRESULT CMultiSAP::InitializeEnvironment() { HRESULT hr; // m_hMonitor = MonitorFromWindow(m_hwndApp, MONITOR_DEFAULTTOPRIMARY); hr = CreateDefaultAllocatorPresenter(); if (hr != S_OK) return hr; BITMAPINFOHEADER bi = { sizeof(BITMAPINFOHEADER), // biSize 640, // biWidth 480, // biHeight 1, // biPlanes 0, // biBitCount BI_RGB, // biCompression 0, // biSizeImage, 0, // biXpelsPerMeter 0, // biYPelsPerMeter 0, // biClrUsed 0 // biClrImportant }; VMRALLOCATIONINFO ai = { AMAP_3D_TARGET, // dwFlags &bi, // lpHdr NULL, // lpPicFmt {4, 3}, // szAspectRatio 1, // dwMinBuffers 1, // dwMaxBuffers 0, // dwInterlaceFlags {640, 480} // szNativeSize }; DWORD dwBuffers = 0; LPDIRECTDRAWSURFACE7 lpDDSurf; hr = m_pAlloc->AllocateSurface(0, &ai, &dwBuffers, &lpDDSurf); if (hr != DD_OK) return hr; DDSURFACEDESC2 ddsd = {sizeof(DDSURFACEDESC2)}; hr = lpDDSurf->GetSurfaceDesc(&ddsd); if (hr != DD_OK) { return hr; } // // Overlay surfaces have these flags set, we need to remove // these flags prior to calling GetAttachedSurface // ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FRONTBUFFER | DDSCAPS_VISIBLE); hr = lpDDSurf->GetAttachedSurface(&ddsd.ddsCaps, &m_lpBackBuffer); m_lpBackBuffer->GetDDInterface((LPVOID *)&m_lpDDObj); // // get the h/w caps for this device // INITDDSTRUCT(m_ddHWCaps); m_lpDDObj->GetCaps(&m_ddHWCaps, NULL); // // Create the device. The device is created off of our back buffer, which // becomes the render target for the newly created device. Note that the // z-buffer must be created BEFORE the device // m_pD3DHelper = new CD3DHelper(m_lpBackBuffer, &hr); if(m_pD3DHelper == NULL || hr != DD_OK) { if(m_pD3DHelper == NULL) { hr = E_OUTOFMEMORY; } delete m_pD3DHelper; } SetRect(&m_rcDst, 0, 0, 640, 480); #ifdef SPARKLE m_pSparkle = new CSparkle(m_lpDDObj); if (m_pSparkle) m_pSparkle->InitializeSparkle(); #endif return hr; }
/******************************Public*Routine******************************\ * PresentImage * \**************************************************************************/ STDMETHODIMP CMpegMovie::PresentImage( DWORD_PTR dwUserID, VMRPRESENTATIONINFO* lpPresInfo ) { #if 0 LPDIRECTDRAWSURFACE7 lpSurface = lpPresInfo->lpSurf; const REFERENCE_TIME rtNow = lpPresInfo->rtStart; const DWORD dwSurfaceFlags = lpPresInfo->dwFlags; if(m_iDuration > 0) { HRESULT hr; RECT rs, rd; DDSURFACEDESC2 ddsdV; INITDDSTRUCT(ddsdV); hr = lpSurface->GetSurfaceDesc(&ddsdV); DDSURFACEDESC2 ddsdP; INITDDSTRUCT(ddsdP); hr = m_pddsPriText->GetSurfaceDesc(&ddsdP); FLOAT fPos = (FLOAT)m_iDuration / 30.0F; FLOAT fPosInv = 1.0F - fPos; SetRect(&rs, 0, 0, MulDiv((int)ddsdV.dwWidth, 30 - m_iDuration, 30), ddsdV.dwHeight); SetRect(&rd, 0, 0, MulDiv((int)ddsdP.dwWidth, 30 - m_iDuration, 30), ddsdP.dwHeight); hr = m_pddsRenderT->Blt(&rd, lpSurface, &rs, DDBLT_WAIT, NULL); SetRect(&rs, 0, 0, MulDiv((int)ddsdP.dwWidth, m_iDuration, 30), ddsdP.dwHeight); SetRect(&rd, (int)ddsdP.dwWidth - MulDiv((int)ddsdP.dwWidth, m_iDuration, 30), 0, ddsdP.dwWidth, ddsdP.dwHeight); hr = m_pddsRenderT->Blt(&rd, m_pddsPriText, &rs, DDBLT_WAIT, NULL); // // need to wait for VBlank before blt-ing // { LPDIRECTDRAW lpdd; hr = m_pddsPrimary->GetDDInterface((LPVOID*)&lpdd); if(SUCCEEDED(hr)) { DWORD dwScanLine; for(; ;) { hr = lpdd->GetScanLine(&dwScanLine); if(hr == DDERR_VERTICALBLANKINPROGRESS) { break; } if(FAILED(hr)) { break; } if((LONG)dwScanLine>= rd.top) { if((LONG)dwScanLine <= rd.bottom) { continue; } } break; } RELEASE(lpdd); } } hr = m_pddsPrimary->Blt(NULL, m_pddsRenderT, NULL, DDBLT_WAIT, NULL); m_iDuration--; if(m_iDuration == 0 && (ddsdV.ddsCaps.dwCaps & DDSCAPS_OVERLAY)) { // need to get the color key visible again. InvalidateRect(m_hwndApp, NULL, FALSE); } return hr; } else { return m_lpDefIP->PresentImage(dwUserID, lpPresInfo); } #endif return m_lpDefIP->PresentImage(dwUserID, lpPresInfo); }
STDMETHODIMP CDX7SubPic::AlphaBlt(RECT* pSrc, RECT* pDst, SubPicDesc* pTarget) { ASSERT(pTarget == nullptr); if (!m_pD3DDev || !m_pSurface || !pSrc || !pDst) { return E_POINTER; } CRect src(*pSrc), dst(*pDst); HRESULT hr; DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); if (FAILED(hr = m_pSurface->GetSurfaceDesc(&ddsd))) { return E_FAIL; } float w = (float)ddsd.dwWidth; float h = (float)ddsd.dwHeight; // Be careful with the code that follows. Some compilers (e.g. Visual Studio 2012) used to miscompile // it in some cases (namely x64 with optimizations /O2 /Ot). This bug led pVertices not to be correctly // initialized and thus the subtitles weren't shown. struct { float x, y, z, rhw; float tu, tv; } pVertices[] = { {(float)dst.left, (float)dst.top, 0.5f, 2.0f, (float)src.left / w, (float)src.top / h}, {(float)dst.right, (float)dst.top, 0.5f, 2.0f, (float)src.right / w, (float)src.top / h}, {(float)dst.left, (float)dst.bottom, 0.5f, 2.0f, (float)src.left / w, (float)src.bottom / h}, {(float)dst.right, (float)dst.bottom, 0.5f, 2.0f, (float)src.right / w, (float)src.bottom / h}, }; for (size_t i = 0; i < _countof(pVertices); i++) { pVertices[i].x -= 0.5f; pVertices[i].y -= 0.5f; } hr = m_pD3DDev->SetTexture(0, m_pSurface); m_pD3DDev->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE); // pre-multiplied src and ... m_pD3DDev->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_bInvAlpha ? D3DBLEND_INVSRCALPHA : D3DBLEND_SRCALPHA); // ... inverse alpha channel for dst m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); if (src == dst) { m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT); m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFG_POINT); } else { m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFG_LINEAR); } m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_NONE); m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP); /*// D3DDEVICEDESC7 d3ddevdesc; m_pD3DDev->GetCaps(&d3ddevdesc); if (d3ddevdesc.dpcTriCaps.dwAlphaCmpCaps & D3DPCMPCAPS_LESS) { m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)0x000000FE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE); m_pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DPCMPCAPS_LESS); } */// if (FAILED(hr = m_pD3DDev->BeginScene())) { return E_FAIL; } hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, pVertices, 4, D3DDP_WAIT); m_pD3DDev->EndScene(); m_pD3DDev->SetTexture(0, nullptr); return S_OK; }