void Screen3D::TakeScreenshot(char* basefilename) { //declarations IDirect3DSurface9* FrontBuffer; //this is our pointer to the memory location containing our copy of the //front buffer IDirect3DSurface9* Thumbnail; HRESULT hr; //Create surface for stuff to be copied to //D3DDevice->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &FrontBuffer, NULL); hr = D3DDevice->CreateOffscreenPlainSurface(100, 75, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH , &Thumbnail, NULL); //now we copy the front buffer into our surface //HRESULT hr = D3DDevice->GetFrontBufferData(0, FrontBuffer); hr = D3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &FrontBuffer); //make sure we got the front buffer if(hr != D3D_OK) { Thumbnail->Release(); FrontBuffer->Release(); return; } //load the image into the thumbnail D3DXLoadSurfaceFromSurface(Thumbnail, NULL, NULL, FrontBuffer, NULL, NULL, D3DX_DEFAULT, 0); //write screen shot to a bitmap file, as well as a thumbnail std::string BmpFileName = "..\\screenshots\\"; std::string ThumbFileName = "..\\screenshots\\_"; BmpFileName += basefilename; BmpFileName += ".bmp"; ThumbFileName += basefilename; ThumbFileName += ".bmp"; D3DXSaveSurfaceToFile(BmpFileName.c_str(), D3DXIFF_BMP, FrontBuffer, NULL, NULL); D3DXSaveSurfaceToFile(ThumbFileName.c_str(), D3DXIFF_BMP, Thumbnail, NULL, NULL); //release the surface so there is no memory leak FrontBuffer->Release(); Thumbnail->Release(); }
//截图 void ScreenShot (char *filename) { IDirect3DSurface9 *tmp = NULL; IDirect3DSurface9 *back = NULL; //生成固定颜色模式的离屏表面(Width和 Height为屏幕或窗口的宽高) Device->CreateOffscreenPlainSurface(Width, Height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tmp, NULL); // 获得BackBuffer的D3D Surface Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back); // Copy一下,,需要时转换颜色格式 D3DXLoadSurfaceFromSurface(tmp, NULL, NULL, back, NULL, NULL, D3DX_FILTER_NONE, 0); // 保存成BMP格式 D3DXSaveSurfaceToFile(filename, D3DXIFF_BMP, tmp, NULL, NULL); // 释放Surface,防止内存泄漏 tmp->Release(); back->Release(); }
bool CApplicationRenderer::CopySurface(LPDIRECT3DSURFACE8 pSurfaceSource, const RECT* rcSource, LPDIRECT3DSURFACE8 pSurfaceDest, const RECT* rcDest) { if (m_Resolution == HDTV_1080i) { //CopRects doesn't work at all in 1080i, D3DXLoadSurfaceFromSurface does but is ridiculously slow... return SUCCEEDED(D3DXLoadSurfaceFromSurface(pSurfaceDest, NULL, rcDest, pSurfaceSource, NULL, rcSource, D3DX_FILTER_NONE, 0)); } else { if (rcDest) { const POINT ptDest = { rcDest->left, rcDest->top }; return SUCCEEDED(g_graphicsContext.Get3DDevice()->CopyRects(pSurfaceSource, rcSource, rcSource?1:0, pSurfaceDest, &ptDest)); } else { const POINT ptDest = { 0, 0 }; return SUCCEEDED(g_graphicsContext.Get3DDevice()->CopyRects(pSurfaceSource, rcSource, rcSource?1:0, pSurfaceDest, &ptDest)); } } }
Texture* TextureFilters::normalMap(Texture* texture, int amplify, bool inPlace) { Texture* newTexture = new Texture(); D3DXComputeNormalMap(newTexture->getD3D9Texture(), texture->getD3D9Texture(), NULL, 0, D3DX_CHANNEL_RED, (float)amplify); LPDIRECT3DSURFACE9 surface; newTexture->getD3D9Texture()->GetSurfaceLevel(0, &surface); D3DXLoadSurfaceFromSurface(newTexture->d3d9Surface, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_NONE, 0); return newTexture; }
void ReplaceTextureLevel(IDirect3DTexture8* srcTexture, IDirect3DTexture8* repTexture, UINT level) { IDirect3DSurface8* src = NULL; IDirect3DSurface8* dest = NULL; if (SUCCEEDED(srcTexture->GetSurfaceLevel(level, &dest))) { if (SUCCEEDED(repTexture->GetSurfaceLevel(level, &src))) { //DumpTexture(srcTexture); if (SUCCEEDED(D3DXLoadSurfaceFromSurface( dest, NULL, NULL, src, NULL, NULL, D3DX_DEFAULT, 0))) { //LogWithNumber(&k_boot,"ReplaceTextureLevel: replacing level %d COMPLETE", level); } else { //LogWithNumber(&k_boot,"ReplaceTextureLevel: replacing level %d FAILED", level); } src->Release(); } dest->Release(); } }
bool CN3Texture::Convert(D3DFORMAT Format, int nWidth, int nHeight, BOOL bGenerateMipMap) { if(m_lpTexture == NULL) return false; D3DSURFACE_DESC dsd; m_lpTexture->GetLevelDesc(0, &dsd); if(0 >= nWidth || 0 >= nHeight) { nWidth = dsd.Width; nHeight = dsd.Height; } LPDIRECT3DTEXTURE8 lpTexOld = m_lpTexture; m_lpTexture = NULL; if(this->Create(nWidth, nHeight, Format, bGenerateMipMap) == false) return false; if(bGenerateMipMap) { LPDIRECT3DSURFACE8 lpTSOld; lpTexOld->GetSurfaceLevel(0, &lpTSOld); this->GenerateMipMap(lpTSOld); // MipMap 생성 lpTSOld->Release(); } else { LPDIRECT3DSURFACE8 lpTSNew; LPDIRECT3DSURFACE8 lpTSOld; m_lpTexture->GetSurfaceLevel(0, &lpTSNew); lpTexOld->GetSurfaceLevel(0, &lpTSOld); D3DXLoadSurfaceFromSurface(lpTSNew, NULL, NULL, lpTSOld, NULL, NULL, D3DX_FILTER_NONE, 0); // 첫번재 레벨 서피스 복사. lpTSOld->Release(); lpTSNew->Release(); } lpTexOld->Release(); lpTexOld = NULL; return true; }
void CGXRenderTexture::LoadTexture(TxtrCacheEntry* pEntry) { #if 0 //This function copies the current color buffer (m_pTexture for this RenderTexture) to pEntry->pTexture bool IsBeingRendered = m_beingRendered; if( IsBeingRendered ) { TXTRBUF_DUMP(TRACE0("Warning, loading from render_texture while it is being rendered")); SetAsRenderTarget(false); //return; } CTexture *pSurf = pEntry->pTexture; TxtrInfo &ti = pEntry->ti; // Need to load texture from the saved back buffer MYLPDIRECT3DTEXTURE pNewTexture = MYLPDIRECT3DTEXTURE(pSurf->GetTexture()); MYLPDIRECT3DSURFACE pNewSurface = NULL; HRESULT res = pNewTexture->GetSurfaceLevel(0,&pNewSurface); MYLPDIRECT3DSURFACE pSourceSurface = NULL; (MYLPDIRECT3DTEXTURE(m_pTexture->GetTexture()))->GetSurfaceLevel(0,&pSourceSurface); int left = (pEntry->ti.Address- m_pInfo->CI_Info.dwAddr )%m_pInfo->CI_Info.bpl + pEntry->ti.LeftToLoad; int top = (pEntry->ti.Address- m_pInfo->CI_Info.dwAddr)/m_pInfo->CI_Info.bpl + pEntry->ti.TopToLoad; RECT srcrect = {uint32(left*m_pInfo->scaleX) ,uint32(top*m_pInfo->scaleY), uint32(min(m_width, left+(int)ti.WidthToLoad)*m_pInfo->scaleX), uint32(min(m_height,top+(int)ti.HeightToLoad)*m_pInfo->scaleY) }; if( pNewSurface != NULL && pSourceSurface != NULL ) { if( left < m_width && top<m_height ) { RECT dstrect = {0,0,ti.WidthToLoad,ti.HeightToLoad}; HRESULT res = D3DXLoadSurfaceFromSurface(pNewSurface,NULL,&dstrect,pSourceSurface,NULL,&srcrect,D3DX_FILTER_POINT ,0xFF000000); DEBUGGER_IF_DUMP(( res != S_OK), {DebuggerAppendMsg("Error to reload texture from render_texture, res=%x", res);} );
INT TcolorMap::OnResetDevice() { HRESULT hr; if(NULL == m_pTx) { hr = D3DXCreateTexture(m_pDev, m_iW, m_iH, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pTx); if(FAILED(hr)) return -1; m_pTx->GetSurfaceLevel(0,&m_pSf); m_pDev->GetRenderTarget(0,&m_pBckC); m_pDev->GetDepthStencilSurface(&m_pBckD); if(FAILED(hr)) return -1; } if(m_pTxT) { PDSF pSrc; PDSF pDst =m_pSf; hr = m_pTxT->GetSurfaceLevel(0,&pSrc); hr = D3DXLoadSurfaceFromSurface(pDst, NULL, NULL, m_pSf, NULL, NULL, D3DX_FILTER_NONE, 0x0); if(FAILED(hr)) return -1; SAFE_RELEASE( pSrc ); SAFE_RELEASE( m_pTxT ); } return 0; }
bool CN3Texture::GenerateMipMap(LPDIRECT3DSURFACE8 lpSurfSrc) { if(m_lpTexture == NULL) return false; // MipMap 이 몇개 필요한지 계산.. int nMMC = m_lpTexture->GetLevelCount(); int nMMC2 = 0; for(int nW = m_Header.nWidth, nH = m_Header.nHeight; nW >=4 && nH >= 4; nW /=2, nH /= 2) nMMC2++; bool bNeedReleaseSurf = false; if(NULL == lpSurfSrc) { bNeedReleaseSurf = true; if(D3D_OK != m_lpTexture->GetSurfaceLevel(0, &lpSurfSrc)) return false; } HRESULT rval = D3D_OK; if(nMMC < nMMC2) // 적으면 새로 생성.. { LPDIRECT3DTEXTURE8 lpTexOld = m_lpTexture; m_lpTexture = NULL; rval = this->CreateFromSurface(lpSurfSrc, m_Header.Format, TRUE); if(bNeedReleaseSurf) { lpSurfSrc->Release(); lpSurfSrc = NULL; } lpTexOld->Release(); lpTexOld = NULL; if(D3D_OK == rval) { m_Header.bMipMap = TRUE; return true; } else { m_Header.bMipMap = FALSE; return FALSE; } } else // MipMap 이 있으면 그냥 표면만 복사 { if(false == bNeedReleaseSurf) // 다른 서피스에서 복사해야 되는 거면 0 레벨도 복사.. { LPDIRECT3DSURFACE8 lpSurfDest; m_lpTexture->GetSurfaceLevel(0, &lpSurfDest); DWORD dwFilter = D3DX_FILTER_TRIANGLE; // 기본 필터는 없다.. HRESULT rval = D3DXLoadSurfaceFromSurface(lpSurfDest, NULL, NULL, lpSurfSrc, NULL, NULL, dwFilter, 0); // 작은 맵 체인에 서피스 이미지 축소 복사 lpSurfDest->Release(); lpSurfDest = NULL; } for(int i = 1; i < nMMC2; i++) { LPDIRECT3DSURFACE8 lpSurfDest, lpSurfUp; m_lpTexture->GetSurfaceLevel(i-1, &lpSurfUp); m_lpTexture->GetSurfaceLevel(i, &lpSurfDest); DWORD dwFilter = D3DX_FILTER_TRIANGLE; // 기본 필터는 없다.. HRESULT rval = D3DXLoadSurfaceFromSurface(lpSurfDest, NULL, NULL, lpSurfUp, NULL, NULL, dwFilter, 0); // 작은 맵 체인에 서피스 이미지 축소 복사 lpSurfDest->Release(); lpSurfUp->Release(); } if(bNeedReleaseSurf) { lpSurfSrc->Release(); lpSurfSrc = NULL; } if(D3D_OK == rval) { m_Header.bMipMap = TRUE; return true; } else { m_Header.bMipMap = FALSE; return FALSE; } } }
//----------------------------------------------------------------------------- // Name: InitDeviceObjects // Desc: //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::InitDeviceObjects() { HRESULT hr; TCHAR sz[512]; m_bDrawWater = TRUE; m_bDrawCaustics = TRUE; m_bDrawEnvironment = TRUE; // Initialize the font's internal textures m_pFont->InitDeviceObjects( m_pd3dDevice ); m_pFontSmall->InitDeviceObjects( m_pd3dDevice ); // Floor DXUtil_FindMediaFile(sz, _T("Water.bmp")); D3DXCreateTextureFromFileEx(m_pd3dDevice, sz, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &m_pFloorTex); // Sky TCHAR* szSkyTex[6] = { _T("lobbyxpos.bmp"), _T("lobbyxneg.bmp"), _T("lobbyypos.bmp"), _T("lobbyyneg.bmp"), _T("lobbyzneg.bmp"), _T("lobbyzpos.bmp") }; for(UINT i = 0; i < 6; i++) { DXUtil_FindMediaFile(sz, szSkyTex[i]); D3DXCreateTextureFromFileEx(m_pd3dDevice, sz, D3DX_DEFAULT, D3DX_DEFAULT, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &m_pSkyTex[i]); } if(SUCCEEDED(D3DXCreateCubeTexture(m_pd3dDevice, 128, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, &m_pSkyCubeTex))) { for(UINT i = 0; i < 6; i++) { if(m_pSkyTex[i]) { IDirect3DSurface8 *pSrc; IDirect3DSurface8 *pDest; m_pSkyTex[i]->GetSurfaceLevel(0, &pSrc); m_pSkyCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES) i, 0, &pDest); if(pSrc && pDest) D3DXLoadSurfaceFromSurface(pDest, NULL, NULL, pSrc, NULL, NULL, D3DX_DEFAULT, 0); SAFE_RELEASE(pDest); SAFE_RELEASE(pSrc); } } D3DXFilterCubeTexture(m_pSkyCubeTex, NULL, 0, D3DX_DEFAULT); } // OnCreateDevice if(FAILED(hr = m_Water.OnCreateDevice(m_pd3dDevice))) return hr; if(FAILED(hr = m_Environment.OnCreateDevice(m_pd3dDevice))) return hr; return S_OK; }
bool CN3Texture::Save(HANDLE hFile) { if(NULL == m_lpTexture) return false; CN3BaseFileAccess::Save(hFile); DWORD dwRWC = 0; D3DSURFACE_DESC sd; m_lpTexture->GetLevelDesc(0, &sd); int nMMC = m_lpTexture->GetLevelCount(); (nMMC > 1) ? m_Header.bMipMap = TRUE : m_Header.bMipMap = FALSE; if(TRUE == m_Header.bMipMap) // MipMap 갯수가 맞는지 확인.. { int nMMC2 = 0; for(int nW = sd.Width, nH = sd.Height; nW >=4 && nH >= 4; nW /=2, nH /= 2) nMMC2++; if(nMMC < nMMC2) { #ifdef _N3GAME CLogWriter::Write("N3Texture save warning - Invalid MipMap Count (%s)", m_szFileName.c_str()); #endif m_Header.bMipMap = FALSE; nMMC = 1; } else { nMMC = nMMC2; } } m_Header.szID[0] = 'N'; m_Header.szID[1] = 'T'; m_Header.szID[2] = 'F'; m_Header.szID[3] = 3; // Noah Texture File Ver '3' m_Header.nWidth = sd.Width; m_Header.nHeight = sd.Height; m_Header.bMipMap = (nMMC > 1) ? TRUE : FALSE; WriteFile(hFile, &m_Header, sizeof(m_Header), &dwRWC, NULL); // 헤더를 쓰고 if(m_lpTexture == NULL) return false; if( D3DFMT_DXT1 == sd.Format || D3DFMT_DXT2 == sd.Format || D3DFMT_DXT3 == sd.Format || D3DFMT_DXT4 == sd.Format || D3DFMT_DXT5 == sd.Format ) { D3DLOCKED_RECT LR; for(int i = 0; i < nMMC; i++) { m_lpTexture->GetLevelDesc(i, &sd); m_lpTexture->LockRect(i, &LR, NULL, NULL); WriteFile(hFile, (BYTE*)LR.pBits, sd.Size, &dwRWC, NULL); // 일렬로 된 데이터를 쓰고.. m_lpTexture->UnlockRect(i); } // 추가로 압축되지 않은 형식을 써준다.. 절반 크기이다. // 압축되지 않은 형식을 해상도를 한단계 낮추어서 저장. LPDIRECT3DSURFACE8 lpSurfSrc = NULL, lpSurfDest = NULL; D3DFORMAT fmtExtra = D3DFMT_UNKNOWN; if(D3DFMT_DXT1 == sd.Format) fmtExtra = D3DFMT_A1R5G5B5; else fmtExtra = D3DFMT_A4R4G4B4; int nMMC2 = nMMC - 1; if(nMMC == 1) nMMC2 = nMMC; for(i = 0; i < nMMC2; i++) { m_lpTexture->GetLevelDesc(i, &sd); m_lpTexture->GetSurfaceLevel(i, &lpSurfSrc); int nW = sd.Width / 2, nH = sd.Height / 2; s_lpD3DDev->CreateImageSurface(nW, nH, fmtExtra, &lpSurfDest); D3DXLoadSurfaceFromSurface(lpSurfDest, NULL, NULL, lpSurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0); // 서피스 복사. int nPixelSize = 2; lpSurfDest->LockRect(&LR, NULL, NULL); for(int y = 0; y < nH; y++) { WriteFile(hFile, (BYTE*)LR.pBits + y * LR.Pitch, nW * 2, &dwRWC, NULL); } lpSurfDest->UnlockRect(); lpSurfDest->Release(); lpSurfDest = NULL; lpSurfSrc->Release(); lpSurfSrc = NULL; } if(nMMC == 1 && m_Header.nWidth >= 1024) // 부두를 위해 256 * 256 짜리 하나 더 저장해준다.. { m_lpTexture->GetLevelDesc(0, &sd); m_lpTexture->GetSurfaceLevel(0, &lpSurfSrc); int nW = 256, nH = 256; s_lpD3DDev->CreateImageSurface(nW, nH, fmtExtra, &lpSurfDest); D3DXLoadSurfaceFromSurface(lpSurfDest, NULL, NULL, lpSurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0); // 서피스 복사. int nPixelSize = 2; lpSurfDest->LockRect(&LR, NULL, NULL); for(int y = 0; y < nH; y++) { WriteFile(hFile, (BYTE*)LR.pBits + y * LR.Pitch, nW * 2, &dwRWC, NULL); } lpSurfDest->UnlockRect(); lpSurfDest->Release(); lpSurfDest = NULL; lpSurfSrc->Release(); lpSurfSrc = NULL; } } else // 일반적인 포맷이면. { int nPixelSize = 0; if( D3DFMT_A1R5G5B5 == sd.Format || D3DFMT_A4R4G4B4 == sd.Format) nPixelSize = 2; else if(D3DFMT_R8G8B8 == sd.Format) nPixelSize = 3; else if(D3DFMT_A8R8G8B8 == sd.Format || D3DFMT_X8R8G8B8 == sd.Format) nPixelSize = 4; else { __ASSERT(0, "this Texture Format Not Supported"); } D3DLOCKED_RECT LR; for(int i = 0; i < nMMC; i++) { m_lpTexture->GetLevelDesc(i, &sd); m_lpTexture->LockRect(i, &LR, NULL, 0); // 각 레벨 Lock int nH = sd.Height; for(int y = 0; y < nH; y++) // 그냥 픽셀 저장.. WriteFile(hFile, (BYTE*)LR.pBits + y * LR.Pitch, sd.Width * nPixelSize, &dwRWC, NULL); m_lpTexture->UnlockRect(i); } if(nMMC == 1 && m_Header.nWidth >= 512) // 부두를 위해 256 * 256 짜리 하나 더 저장해준다.. { LPDIRECT3DSURFACE8 lpSurfSrc = NULL, lpSurfDest = NULL; m_lpTexture->GetLevelDesc(0, &sd); m_lpTexture->GetSurfaceLevel(0, &lpSurfSrc); int nW = 256, nH = 256; s_lpD3DDev->CreateImageSurface(nW, nH, sd.Format, &lpSurfDest); HRESULT rval = D3DXLoadSurfaceFromSurface(lpSurfDest, NULL, NULL, lpSurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0); // 서피스 복사. lpSurfDest->LockRect(&LR, NULL, NULL); for(int y = 0; y < nH; y++) { WriteFile(hFile, (BYTE*)LR.pBits + y * LR.Pitch, nW * 2, &dwRWC, NULL); } lpSurfDest->UnlockRect(); lpSurfDest->Release(); lpSurfDest = NULL; lpSurfSrc->Release(); lpSurfSrc = NULL; } } return true; }
HRESULT CDxtexDoc::LoadAlphaIntoSurface(CString& strPath, LPDIRECT3DSURFACE9 psurf) { HRESULT hr; D3DSURFACE_DESC sd; LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev(); LPDIRECT3DTEXTURE9 ptexAlpha; LPDIRECT3DSURFACE9 psurfAlpha; LPDIRECT3DSURFACE9 psurfTarget; psurf->GetDesc(&sd); // Load the alpha BMP into psurfAlpha, a new A8R8G8B8 surface hr = D3DXCreateTextureFromFileEx(pd3ddev, strPath, sd.Width, sd.Height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &ptexAlpha); hr = ptexAlpha->GetSurfaceLevel(0, &psurfAlpha); // Copy the target surface into an A8R8G8B8 surface hr = pd3ddev->CreateOffscreenPlainSurface(sd.Width, sd.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &psurfTarget, NULL); hr = D3DXLoadSurfaceFromSurface(psurfTarget, NULL, NULL, psurf, NULL, NULL, D3DX_DEFAULT, 0); // Fill in the alpha channels of psurfTarget based on the blue channel of psurfAlpha D3DLOCKED_RECT lrSrc; D3DLOCKED_RECT lrDest; hr = psurfAlpha->LockRect(&lrSrc, NULL, D3DLOCK_READONLY); hr = psurfTarget->LockRect(&lrDest, NULL, 0); DWORD xp; DWORD yp; DWORD* pdwRowSrc = (DWORD*)lrSrc.pBits; DWORD* pdwRowDest = (DWORD*)lrDest.pBits; DWORD* pdwSrc; DWORD* pdwDest; DWORD dwAlpha; LONG dataBytesPerRow = 4 * sd.Width; for (yp = 0; yp < sd.Height; yp++) { pdwSrc = pdwRowSrc; pdwDest = pdwRowDest; for (xp = 0; xp < sd.Width; xp++) { dwAlpha = *pdwSrc << 24; *pdwDest &= 0x00ffffff; *pdwDest |= dwAlpha; pdwSrc++; pdwDest++; } pdwRowSrc += lrSrc.Pitch / 4; pdwRowDest += lrDest.Pitch / 4; } psurfAlpha->UnlockRect(); psurfTarget->UnlockRect(); // Copy psurfTarget back into real surface hr = D3DXLoadSurfaceFromSurface(psurf, NULL, NULL, psurfTarget, NULL, NULL, D3DX_DEFAULT, 0); // Release allocated interfaces ReleasePpo(&psurfTarget); ReleasePpo(&psurfAlpha); ReleasePpo(&ptexAlpha); return S_OK; }
void ConvertFile(const char* Dir, const char* Filename, double MaxMSE) { HRESULT hr; LPDIRECT3DSURFACE8 pSrcSurf = NULL; char OutFilename[52]; if (Dir) _snprintf(OutFilename, 52, "%s\\%s", Dir, Filename); else _snprintf(OutFilename, 52, "%s", Filename); OutFilename[51] = 0; printf("%s: ", OutFilename); TRACE1("%s:\n", OutFilename); int n = strlen(OutFilename); if (n < 40) printf("%*c", 40-n, ' '); if (pSrcSurf) pSrcSurf->Release(); pSrcSurf = NULL; // Load up the file D3DXIMAGE_INFO info; hr = D3DXGetImageInfoFromFile(Filename, &info); CheckHR(hr); PrintImageInfo(info); UINT Width = PadPow2(info.Width); UINT Height = PadPow2(info.Height); float Waste = 100.f * (float)(Width * Height - info.Width * info.Height) / (float)(Width * Height); UncompressedSize += Width * Height * 4; TotalSrcPixels += info.Width * info.Height; TotalDstPixels += Width * Height; // Special case for 256-colour files - just directly drop into a P8 xpr if (info.Format == D3DFMT_P8) { hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pSrcSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromFile(pSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL); CheckHR(hr); FixTransparency(pSrcSurf); if (Width * Height > 4096) { // DXT1 for P8s if lossless and more than 4k image LPDIRECT3DSURFACE8 pTempSurf; hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pTempSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromSurface(pTempSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0); CheckHR(hr); double CMSE, AMSE; TRACE0(" Checking DXT1: "); if (!GetFormatMSE(info, pTempSurf, D3DFMT_DXT1, CMSE, AMSE)) { pTempSurf->Release(); return; } TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE); if (CMSE <= 1e-6 && AMSE <= 1e-6) { printf("DXT1 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: DXT1\n"); WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_DXT1, NULL); pTempSurf->Release(); return; } pTempSurf->Release(); } printf("P8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: P8\n"); LPDIRECT3DSURFACE8 pTempSurf; DWORD pal[256]; ConvertP8(pSrcSurf, pTempSurf, pal, info); WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_P8, pal); pTempSurf->Release(); return; } // test linear format versus non-linear format // Linear format requires 64 pixel aligned width, whereas // Non-linear format requires power of 2 width and height bool useLinearFormat(false); UINT linearWidth = (info.Width + 0x3f) & ~0x3f; if (AllowLinear && linearWidth * info.Height < Width * Height) useLinearFormat = true; hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pSrcSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromFile(pSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL); CheckHR(hr); // create the linear version as well LPDIRECT3DSURFACE8 pLinearSrcSurf = NULL; if (useLinearFormat) { hr = pD3DDevice->CreateImageSurface(linearWidth, info.Height, D3DFMT_A8R8G8B8, &pLinearSrcSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromFile(pLinearSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL); CheckHR(hr); } // special case for small files - all textures are alloced on page granularity so just output uncompressed // dxt is crap on small files anyway if (Width * Height <= 1024) { if (useLinearFormat) { // correct sizing amounts UncompressedSize -= Width * Height * 4; UncompressedSize += linearWidth * info.Height * 4; TotalDstPixels -= Width * Height; TotalDstPixels += linearWidth * info.Height; Waste = 100.f * (float)(linearWidth * info.Height - info.Width * info.Height) / (float)(linearWidth * info.Height); printf("LIN_A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", linearWidth, info.Height, Waste); TRACE0(" Selected Format: LIN_A8R8G8B8\n"); WriteXPR(OutFilename, info, pLinearSrcSurf, XB_D3DFMT_LIN_A8R8G8B8, NULL); } else { printf("A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: A8R8G8B8\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_A8R8G8B8, NULL); } return; } FixTransparency(pSrcSurf); // Find the best format within specified tolerance double CMSE, AMSE[2]; // DXT1 is the preferred format as it's smallest TRACE0(" Checking DXT1: "); if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT1, CMSE, AMSE[0])) return; TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]); if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE) { printf("DXT1 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: DXT1\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT1, NULL); return; } // Use P8 is possible as it's lossless LPDIRECT3DSURFACE8 pTempSurf; DWORD pal[256]; if (ConvertP8(pSrcSurf, pTempSurf, pal, info)) { printf("P8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: P8\n"); WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_P8, pal); pTempSurf->Release(); return; } // DXT3/5 are the same size so use whichever is better if good enough // CMSE will be equal for both TRACE0(" Checking DXT3: "); if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT3, CMSE, AMSE[0])) return; TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]); TRACE0(" Checking DXT5: "); if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT5, CMSE, AMSE[1])) return; TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[1]); if (AMSE[0] <= AMSE[1]) { if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE) { printf("DXT3 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: DXT3\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT3, NULL); return; } } else { if (CMSE <= MaxMSE && AMSE[1] <= MaxMSE) { printf("DXT5 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: DXT5\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT5, NULL); return; } } // No good compressed format so use uncompressed // A1R5G5B5 is worth a try I guess... TRACE0(" Checking A1R5G5B5: "); if (!GetFormatMSE(info, pSrcSurf, D3DFMT_A1R5G5B5, CMSE, AMSE[0])) return; TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]); if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE) { printf("A1R5G5B5 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: A1R5G5B5\n"); LPDIRECT3DSURFACE8 pTempSurf; hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A1R5G5B5, &pTempSurf); CheckHR(hr); hr = D3DXLoadSurfaceFromSurface(pTempSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0); CheckHR(hr); WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_A1R5G5B5, NULL); pTempSurf->Release(); return; } // Use A8R8G8B8 if (useLinearFormat) { // correct sizing information UncompressedSize -= Width * Height * 4; UncompressedSize += linearWidth * info.Height * 4; TotalDstPixels -= Width * Height; TotalDstPixels += linearWidth * info.Height; Waste = 100.f * (float)(linearWidth * info.Height - info.Width * info.Height) / (float)(linearWidth * info.Height); printf("LIN_A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", linearWidth, info.Height, Waste); TRACE0(" Selected Format: LIN_A8R8G8B8\n"); WriteXPR(OutFilename, info, pLinearSrcSurf, XB_D3DFMT_LIN_A8R8G8B8, NULL); } else { printf("A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste); TRACE0(" Selected Format: A8R8G8B8\n"); WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_A8R8G8B8, NULL); } if (pSrcSurf) pSrcSurf->Release(); }
void CDxtexDoc::OpenSubsurface(D3DCUBEMAP_FACES FaceType, LONG lwMip, LONG lwSlice) { HRESULT hr; CString fileName; LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev(); LPDIRECT3DTEXTURE9 ptex = NULL; LPDIRECT3DSURFACE9 psurfOrig = NULL; LPDIRECT3DSURFACE9 psurfNew = NULL; if (!PromptForBmp(&fileName)) return; if (IsVolumeMap()) { hr = D3DXCreateTextureFromFile(pd3ddev, fileName, &ptex); hr = ptex->GetSurfaceLevel(0, &psurfOrig); } else if (IsCubeMap()) { hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexOrig)->GetCubeMapSurface(FaceType, lwMip, &psurfOrig); if (m_ptexNew != NULL) hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexNew)->GetCubeMapSurface(FaceType, lwMip, &psurfNew); hr = D3DXLoadSurfaceFromFile(psurfOrig, NULL, NULL, fileName, NULL, D3DX_DEFAULT, 0, NULL); } else { hr = ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetSurfaceLevel(lwMip, &psurfOrig); if (m_ptexNew != NULL) hr = ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetSurfaceLevel(lwMip, &psurfNew); hr = D3DXLoadSurfaceFromFile(psurfOrig, NULL, NULL, fileName, NULL, D3DX_DEFAULT, 0, NULL); } // Look for "foo_a.bmp" for alpha channel int i = fileName.ReverseFind('.'); fileName = fileName.Left(i) + "_a.bmp"; CFileStatus status; if (CFile::GetStatus(fileName, status)) { if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig))) return; } if (IsVolumeMap()) { LPDIRECT3DVOLUME9 pvol; hr = ((LPDIRECT3DVOLUMETEXTURE9)m_ptexOrig)->GetVolumeLevel(lwMip, &pvol); hr = LoadVolumeSliceFromSurface(pvol, lwSlice, psurfOrig); ReleasePpo(&pvol); if (m_ptexNew) { hr = ((LPDIRECT3DVOLUMETEXTURE9)m_ptexNew)->GetVolumeLevel(lwMip, &pvol); hr = LoadVolumeSliceFromSurface(pvol, lwSlice, psurfOrig); ReleasePpo(&pvol); } } else if (psurfNew != NULL) { hr = D3DXLoadSurfaceFromSurface(psurfNew, NULL, NULL, psurfOrig, NULL, NULL, D3DX_DEFAULT, 0); } ReleasePpo(&psurfOrig); ReleasePpo(&psurfNew); ReleasePpo(&ptex); SetModifiedFlag(TRUE); UpdateAllViews(NULL, 1); }
void CDxtexDoc::GenerateMipMaps() { LONG lwTempH; LONG lwTempW; LONG lwPowsW; LONG lwPowsH; LPDIRECT3DTEXTURE9 pddsNew = NULL; D3DFORMAT fmt; HRESULT hr; LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev(); LPDIRECT3DTEXTURE9 pmiptex = NULL; LPDIRECT3DCUBETEXTURE9 pcubetex = NULL; LPDIRECT3DVOLUMETEXTURE9 pvoltex = NULL; LPDIRECT3DTEXTURE9 pmiptexNew = NULL; LPDIRECT3DCUBETEXTURE9 pcubetexNew = NULL; LPDIRECT3DVOLUMETEXTURE9 pvoltexNew = NULL; LPDIRECT3DSURFACE9 psurfSrc; LPDIRECT3DSURFACE9 psurfDest; LPDIRECT3DVOLUME9 pvolSrc; LPDIRECT3DVOLUME9 pvolDest; if (IsVolumeMap()) pvoltex = (LPDIRECT3DVOLUMETEXTURE9)m_ptexOrig; else if (IsCubeMap()) pcubetex = (LPDIRECT3DCUBETEXTURE9)m_ptexOrig; else pmiptex = (LPDIRECT3DTEXTURE9)m_ptexOrig; if (pvoltex != NULL) { D3DVOLUME_DESC vd; pvoltex->GetLevelDesc(0, &vd); fmt = vd.Format; } else if (pcubetex != NULL) { D3DSURFACE_DESC sd; pcubetex->GetLevelDesc(0, &sd); fmt = sd.Format; } else { D3DSURFACE_DESC sd; pmiptex->GetLevelDesc(0, &sd); fmt = sd.Format; } lwTempW = m_dwWidth; lwTempH = m_dwHeight; lwPowsW = 0; lwPowsH = 0; while (lwTempW > 0) { lwPowsW++; lwTempW = lwTempW / 2; } while (lwTempH > 0) { lwPowsH++; lwTempH = lwTempH / 2; } m_numMips = lwPowsW > lwPowsH ? lwPowsW : lwPowsH; // Create destination mipmap surface - same format as source if (pvoltex != NULL) { if (FAILED(hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, m_numMips, 0, fmt, D3DPOOL_SYSTEMMEM, &pvoltexNew, NULL))) { goto LFail; } hr = pvoltex->GetVolumeLevel(0, &pvolSrc); hr = pvoltexNew->GetVolumeLevel(0, &pvolDest); hr = D3DXLoadVolumeFromVolume(pvolDest, NULL, NULL, pvolSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&pvolSrc); ReleasePpo(&pvolDest); hr = D3DXFilterVolumeTexture(pvoltexNew, NULL, 0, D3DX_DEFAULT); } else if (pmiptex != NULL) { if (FAILED(hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips, 0, fmt, D3DPOOL_MANAGED, &pmiptexNew, NULL))) { goto LFail; } hr = pmiptex->GetSurfaceLevel(0, &psurfSrc); hr = pmiptexNew->GetSurfaceLevel(0, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); hr = D3DXFilterTexture(pmiptexNew, NULL, 0, D3DX_DEFAULT); } else { if (FAILED(hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips, 0, fmt, D3DPOOL_MANAGED, &pcubetexNew, NULL))) { goto LFail; } hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &psurfSrc); hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_X, 0, &psurfSrc); hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_X, 0, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &psurfSrc); hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Y, 0, &psurfSrc); hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Y, 0, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Z, 0, &psurfSrc); hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Z, 0, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Z, 0, &psurfSrc); hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Z, 0, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); hr = D3DXFilterCubeTexture(pcubetexNew, NULL, 0, D3DX_DEFAULT); } ReleasePpo(&m_ptexOrig); if (pvoltexNew != NULL) m_ptexOrig = pvoltexNew; else if (pcubetexNew != NULL) m_ptexOrig = pcubetexNew; else m_ptexOrig = pmiptexNew; if (m_ptexNew != NULL) { // Rather than filtering down the (probably-compressed) m_ptexNew // top level, compress each mip level from the (probably-uncompressed) // m_ptexOrig levels. if (pvoltexNew != NULL) { D3DVOLUME_DESC vd; ((LPDIRECT3DVOLUMETEXTURE9)m_ptexNew)->GetLevelDesc(0, &vd); fmt = vd.Format; } else if (pcubetexNew != NULL) { D3DSURFACE_DESC sd; ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetLevelDesc(0, &sd); fmt = sd.Format; } else { D3DSURFACE_DESC sd; ((LPDIRECT3DCUBETEXTURE9)m_ptexNew)->GetLevelDesc(0, &sd); fmt = sd.Format; } Compress(fmt, FALSE); } m_bTitleModsChanged = TRUE; // Generate title bar update UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers SetModifiedFlag(); return; LFail: ReleasePpo(&pddsNew); }
QRect CFont::_findGlyphRect(int width, int height) { Row* row = nullptr; float bestRatio = 0; for (auto it = m_rows.begin(); it != m_rows.end() && !row; ++it) { const float ratio = static_cast<float>(height) / (*it).height; if ((ratio < 0.7f) || (ratio > 1.f)) continue; if (width > m_textureSize.width() - (*it).width) continue; if (ratio < bestRatio) continue; row = &(*it); bestRatio = ratio; } if (!row) { int rowHeight = height + height / 10; while (m_nextRow + rowHeight >= m_textureSize.width()) { D3DCAPS9 d3dCaps; m_device->GetDeviceCaps(&d3dCaps); if ((m_textureSize.width() * 2 <= d3dCaps.MaxTextureWidth) && (m_textureSize.height() * 2 <= d3dCaps.MaxTextureHeight)) { LPDIRECT3DTEXTURE9 pNewTexture; m_device->CreateTexture(m_textureSize.width() * 2, m_textureSize.height() * 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pNewTexture, null); LPDIRECT3DSURFACE9 destSurface = null; LPDIRECT3DSURFACE9 srcSurface = null; pNewTexture->GetSurfaceLevel(0, &destSurface); m_texture->GetSurfaceLevel(0, &srcSurface); const RECT rect[] = { 0, 0, m_textureSize.width(), m_textureSize.height() }; D3DXLoadSurfaceFromSurface(destSurface, null, rect, srcSurface, null, rect, D3DX_DEFAULT, 0); Release(srcSurface); Release(destSurface); Release(m_texture); m_texture = pNewTexture; m_textureSize.rwidth() *= 2; m_textureSize.rheight() *= 2; for (auto it = m_glyphs.begin(); it != m_glyphs.end(); it++) { (*it).tu1 /= 2.0f; (*it).tu2 /= 2.0f; (*it).tv1 /= 2.0f; (*it).tv2 /= 2.0f; } } else { qWarning("Failed to add a new character to the font: the maximum texture size has been reached"); return QRect(0, 0, 2, 2); } } m_rows.push_back(Row(m_nextRow, rowHeight)); m_nextRow += rowHeight; row = &m_rows.back(); } const QRect rect(QPoint(row->width, row->top), QPoint(row->width + width, row->top + height)); row->width += width; return rect; }
//----------------------------------------------------------------------------- // PresentSwapChain // // Presents a swap chain that contains a video frame by doing a callback // via the sink. // // pSwapChain: Pointer to the swap chain. // pSurface: Pointer to the swap chain's back buffer surface. //----------------------------------------------------------------------------- HRESULT D3DPresentEngine::PresentSwapChain(IDirect3DSwapChain9* pSwapChain, IDirect3DSurface9* pSurface) { HRESULT hr = S_OK; if (m_hwnd == NULL) { return MF_E_INVALIDREQUEST; } if(!m_pRenderSurface) { D3DSURFACE_DESC desc; // Get the surface description pSurface->GetDesc(&desc); // Create a surface the same size as our sample hr = this->m_pDevice->CreateRenderTarget(desc.Width, desc.Height, desc.Format, desc.MultiSampleType, desc.MultiSampleQuality, true, &m_pRenderSurface, NULL); if(hr != S_OK) goto bottom; } if(m_pRenderSurface) { D3DSURFACE_DESC originalDesc; // Get the surface description of this sample pSurface->GetDesc(&originalDesc); D3DSURFACE_DESC renderDesc; // Get the surface description of the render surface m_pRenderSurface->GetDesc(&renderDesc); // Compare the descriptions to make sure they match if(originalDesc.Width != renderDesc.Width || originalDesc.Height != renderDesc.Height || originalDesc.Format != renderDesc.Format) { // Release the old render surface SAFE_RELEASE(m_pRenderSurface); // Create a new render surface that matches the size of this surface hr = this->m_pDevice->CreateRenderTarget(originalDesc.Width, originalDesc.Height, originalDesc.Format, originalDesc.MultiSampleType, originalDesc.MultiSampleQuality, true, &m_pRenderSurface, NULL); if(hr != S_OK) goto bottom; } } if(m_pRenderSurface) { // Copy the passed surface to our rendered surface hr = D3DXLoadSurfaceFromSurface(m_pRenderSurface, NULL, NULL, pSurface, NULL, NULL, D3DX_FILTER_NONE, 0); } if(hr != S_OK) goto bottom; // Do the callback, passing the rendered surface if(m_pCallback) hr = m_pCallback->PresentSurfaceCB(m_pRenderSurface); LOG_MSG_IF_FAILED(L"D3DPresentEngine::PresentSwapChain failed.", hr); bottom: return hr; }
/** * Locks rectangle on both (left/right) surfaces. ***/ HRESULT WINAPI D3D9ProxySurface::LockRect(D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { SHOW_CALL("D3D9ProxySurface::LockRect"); D3DSURFACE_DESC desc; m_pActualSurface->GetDesc(&desc); if (desc.Pool != D3DPOOL_DEFAULT) { //Can't really handle stereo for this, so just lock on the original texture return m_pActualSurface->LockRect(pLockedRect, pRect, Flags); } //Guard against multithreaded access as this could be causing us problems std::lock_guard<std::mutex> lck (m_mtx); //Create lockable system memory surfaces if (pRect && !fullSurface) { lockedRects.push_back(*pRect); } else { lockedRects.clear(); fullSurface = true; } HRESULT hr = D3DERR_INVALIDCALL; IDirect3DSurface9 *pSurface = NULL; bool createdTexture = false; if (!lockableSysMemTexture) { hr = m_pOwningDevice->getActual()->CreateTexture(desc.Width, desc.Height, 1, 0, desc.Format, D3DPOOL_SYSTEMMEM, &lockableSysMemTexture, NULL); if (FAILED(hr)) return hr; createdTexture = true; } lockableSysMemTexture->GetSurfaceLevel(0, &pSurface); //Only copy the render taget (if possible) on the creation of the memory texture if (createdTexture) { hr = D3DXLoadSurfaceFromSurface(pSurface, NULL, NULL, m_pActualSurface, NULL, NULL, D3DX_DEFAULT, 0); if (FAILED(hr)) { #ifdef _DEBUG vireio::debugf("Failed: D3DXLoadSurfaceFromSurface hr = 0x%0.8x", hr); #endif } } //And finally, lock the memory surface hr = pSurface->LockRect(pLockedRect, pRect, Flags); if (FAILED(hr)) return hr; lockedRect = *pLockedRect; pSurface->Release(); return hr; }
HRESULT RSManager::redirectSetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) { nrts++; //if(RenderTargetIndex==0) lastReplacement = -1; //SurfSurfMap::iterator it = renderTexSurfTargets.find(pRenderTarget); //if(it != renderTexSurfTargets.end()) { // SDLOG(1, "Redirected SetRenderTarget(%d, %p) to %p\n", RenderTargetIndex, pRenderTarget, it->second); // if(capturing) dumpSurface("redirectRenderTarget", it->second); // lastReplacement = renderTexSurfIndices[pRenderTarget]; // return d3ddev->SetRenderTarget(RenderTargetIndex, it->second); //} //if(capturing && hudStarted) { // //SurfIntMap::iterator it = renderTexSurfIndices.find(pRenderTarget); // //if(it != renderTexSurfIndices.end()) { // dumpSurface("hudTarget", pRenderTarget); // capturing = false; // //} //} // determine where we are rendering to //{ // SurfIntMap::iterator it = mainRenderSurfIndices.find(pRenderTarget); // if(it != mainRenderSurfIndices.end()) { // SDLOG(4, " - rendersurface #%d\n", it->second); // } else { // if(IDirect3DTexture9* tex = getSurfTexture(pRenderTarget)) { // TexIntMap::iterator it = mainRenderTexIndices.find(tex); // if(it != mainRenderTexIndices.end()) { // SDLOG(4, " - rendertexture #%d\n", it->second); // } // tex->Release(); // } else { // IDirect3DSurface9* backBuffer; // d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); // if(pRenderTarget == backBuffer) { // SDLOG(4, " - backbuffer\n"); // } // backBuffer->Release(); // } // } //} if(capturing) { IDirect3DSurface9 *oldRenderTarget, *depthStencilSurface; d3ddev->GetRenderTarget(0, &oldRenderTarget); d3ddev->GetDepthStencilSurface(&depthStencilSurface); char buffer[64]; sprintf(buffer, "%03d_oldRenderTarget_%p_.tga", nrts, oldRenderTarget); SDLOG(0, "Capturing surface %p as %s\n", oldRenderTarget, buffer); D3DXSaveSurfaceToFile(buffer, D3DXIFF_TGA, oldRenderTarget, NULL, NULL); if(depthStencilSurface) { sprintf(buffer, "%03d_oldRenderTargetDepth_%p_.tga", nrts, oldRenderTarget); SDLOG(0, "Capturing depth surface %p as %s\n", depthStencilSurface, buffer); D3DXSaveSurfaceToFile(buffer, D3DXIFF_TGA, depthStencilSurface, NULL, NULL); } SAFERELEASE(oldRenderTarget); SAFERELEASE(depthStencilSurface); } if(nrts == 1) { // we are switching to the RT that will be the main rendering target for this frame // store it for later use mainRT = pRenderTarget; SDLOG(0, "Storing RT as main RT: %p\n", mainRT); } if(nrts == 11) { // we are switching to the RT used to store the Z value in the 24 RGB bits (among other things) // lets store it for later use zSurf = pRenderTarget; SDLOG(0, "Storing RT as Z buffer RT: %p\n", zSurf); } if(mainRT && pRenderTarget == mainRT) { SDLOG(0, "MainRT uses: %d + 1\n", mainRTuses); ++mainRTuses; } // we are switching away from the initial 3D-rendered image, do AA and SSAO if(mainRTuses == 2 && mainRT && zSurf && ((ssao && doSsao) || (doAA && (smaa || fxaa)))) { IDirect3DSurface9 *oldRenderTarget; d3ddev->GetRenderTarget(0, &oldRenderTarget); if(oldRenderTarget == mainRT) { // final renderbuffer has to be from texture, just making sure here if(IDirect3DTexture9* tex = getSurfTexture(oldRenderTarget)) { // check size just to make even more sure D3DSURFACE_DESC desc; oldRenderTarget->GetDesc(&desc); if(desc.Width == Settings::get().getRenderWidth() && desc.Height == Settings::get().getRenderHeight()) { IDirect3DTexture9 *zTex = getSurfTexture(zSurf); //if(takeScreenshot) D3DXSaveTextureToFile("0effect_pre.bmp", D3DXIFF_BMP, tex, NULL); //if(takeScreenshot) D3DXSaveTextureToFile("0effect_z.bmp", D3DXIFF_BMP, zTex, NULL); storeRenderState(); d3ddev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); d3ddev->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE); // perform AA processing if(!lowFPSmode && doAA && (smaa || fxaa)) { if(smaa) smaa->go(tex, tex, rgbaBuffer1Surf, SMAA::INPUT_COLOR); else fxaa->go(tex, rgbaBuffer1Surf); d3ddev->StretchRect(rgbaBuffer1Surf, NULL, oldRenderTarget, NULL, D3DTEXF_NONE); } // perform SSAO if(ssao && doSsao) { ssao->go(tex, zTex, rgbaBuffer1Surf); d3ddev->StretchRect(rgbaBuffer1Surf, NULL, oldRenderTarget, NULL, D3DTEXF_NONE); } restoreRenderState(); zTex->Release(); //if(takeScreenshot) D3DXSaveSurfaceToFile("1effect_buff.bmp", D3DXIFF_BMP, rgbaBuffer1Surf, NULL, NULL); //if(takeScreenshot) D3DXSaveSurfaceToFile("1effect_post.bmp", D3DXIFF_BMP, oldRenderTarget, NULL, NULL); } tex->Release(); } } oldRenderTarget->Release(); } // DoF blur stuff if(gauss && doDofGauss) { IDirect3DSurface9 *oldRenderTarget; d3ddev->GetRenderTarget(0, &oldRenderTarget); D3DSURFACE_DESC desc; oldRenderTarget->GetDesc(&desc); unsigned dofIndex = isDof(desc.Width, desc.Height); if(dofIndex) { doft[dofIndex]++; SDLOG(6,"DOF index: %u, doft: %u\n", dofIndex, doft[dofIndex]); //if(takeScreenshot) { // char buffer[256]; // sprintf(buffer, "dof%1u_doft%1u.bmp", dofIndex, doft[dofIndex]); // D3DXSaveSurfaceToFile(buffer, D3DXIFF_BMP, oldRenderTarget, NULL, NULL); //} if(dofIndex == 1 && doft[1] == 4) { IDirect3DTexture9 *oldRTtex = getSurfTexture(oldRenderTarget); if(oldRTtex) { storeRenderState(); for(size_t i=0; i<Settings::get().getDOFBlurAmount(); ++i) gauss->go(oldRTtex, oldRenderTarget); restoreRenderState(); oldRTtex->Release(); } } } oldRenderTarget->Release(); } // Timing for hudless screenshots if(mainRTuses == 11 && takeScreenshot) { IDirect3DSurface9 *oldRenderTarget; d3ddev->GetRenderTarget(0, &oldRenderTarget); if(oldRenderTarget != mainRT) { static int toggleSS = 0; toggleSS = (toggleSS+1)%2; if(!toggleSS) { takeScreenshot = false; SDLOG(0, "Capturing screenshot\n"); char timebuf[128], buffer[512]; time_t ltime; time(<ime); struct tm *timeinfo; timeinfo = localtime(<ime); strftime(timebuf, 128, "screenshot_%Y-%m-%d_%H-%M-%S.png", timeinfo); sprintf(buffer, "%s\\%s", Settings::get().getScreenshotDir().c_str(), timebuf); SDLOG(0, " - to %s\n", buffer); D3DSURFACE_DESC desc; oldRenderTarget->GetDesc(&desc); IDirect3DSurface9 *convertedSurface; d3ddev->CreateRenderTarget(desc.Width, desc.Height, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, true, &convertedSurface, NULL); D3DXLoadSurfaceFromSurface(convertedSurface, NULL, NULL, oldRenderTarget, NULL, NULL, D3DX_FILTER_POINT, 0); D3DXSaveSurfaceToFile(buffer, D3DXIFF_PNG, convertedSurface, NULL, NULL); convertedSurface->Release(); } } oldRenderTarget->Release(); } if(rddp >= 4) { // we just finished rendering the frame (pre-HUD) IDirect3DSurface9 *oldRenderTarget; d3ddev->GetRenderTarget(0, &oldRenderTarget); // final renderbuffer has to be from texture, just making sure here if(IDirect3DTexture9* tex = getSurfTexture(oldRenderTarget)) { // check size just to make even more sure D3DSURFACE_DESC desc; oldRenderTarget->GetDesc(&desc); if(desc.Width == Settings::get().getRenderWidth() && desc.Height == Settings::get().getRenderHeight()) { // HUD stuff if(hud && doHud && rddp == 9) { SDLOG(0, "Starting HUD rendering\n"); hddp = 0; onHudRT = true; d3ddev->SetRenderTarget(0, rgbaBuffer1Surf); d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0,0,0,0), 0.0f, 0); prevRenderTex = tex; prevRenderTarget = pRenderTarget; tex->Release(); oldRenderTarget->Release(); d3ddev->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA); d3ddev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_ADD); d3ddev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); d3ddev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); return S_OK; } } tex->Release(); } oldRenderTarget->Release(); } if(onHudRT) { finishHudRendering(); } if(rddp < 4 || rddp > 8) rddp = 0; else rddp++; return d3ddev->SetRenderTarget(RenderTargetIndex, pRenderTarget); }
bool DirectXTextureManager::loadTileSetFromTexture(Game *game, wstring dir, wstring sourceImageFileName, int tileWidth, int tileHeight) { // CONVERT THE FILE NAME INTO A WINDOW LONG CHAR wchar_t (LPCWSTR) wstring sourcePath = dir + sourceImageFileName; LPDIRECT3DTEXTURE9 textureToDivide; LPDIRECT3DSURFACE9 surfaceToDivide; //DXLoad //D3DXLoadSurfaceFromMemory() unsigned int result = fillTexture(sourcePath, &textureToDivide); textureToDivide->GetSurfaceLevel(0, &surfaceToDivide);//~15 seconds if (result != S_OK) return false; // DETERMINE THE NUMBER OF TILE ROWS AND COLUMNS D3DSURFACE_DESC surfaceDesc; surfaceToDivide->GetDesc(&surfaceDesc); int textureWidth = surfaceDesc.Width; int textureHeight = surfaceDesc.Height; int columns = textureWidth / tileWidth; int rows = textureHeight / tileHeight; DirectXGraphics *dxg = (DirectXGraphics*)graphics; LPDIRECT3DDEVICE9 graphicsDevice = ((DirectXGraphics*)graphics)->getGraphicsDevice(); // THE TILE SET IMAGE LOADED SUCCESSFULLY, SO LET'S CUT IT UP // MAYBE IF IM FEELING CRAZY LATER ILL MULTI THREAD THIS for (int row = 0; row < rows; row++) { for (int column = 0; column < columns; column++) { LPDIRECT3DTEXTURE9 extractedTexture; LPDIRECT3DSURFACE9 extractedSurface; result = graphicsDevice->CreateRenderTarget(tileWidth, tileHeight, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, false, &extractedSurface, NULL); if (result != S_OK) return false; RECT sourceRect; sourceRect.left = column * tileWidth; sourceRect.right = tileWidth + (column * tileWidth) - 1; sourceRect.top = row * tileHeight; sourceRect.bottom = tileHeight + (row * tileHeight) - 1; graphicsDevice->StretchRect(surfaceToDivide, &sourceRect, extractedSurface, NULL, D3DTEXF_NONE); // BUILD A UNIQUE FILE NAME FOR THIS TEXTURE wstring textureFilename = sourceImageFileName; unsigned int id = wstringTable.getNumWStringsInTable(); wchar_t dot = '.'; int dotIndex = textureFilename.rfind(dot); textureFilename = textureFilename.substr(0, dotIndex); wstringstream idWss; idWss << id; wstring idText; idWss >> idText; textureFilename = textureFilename + idText + L".png"; textureFilename = wstring(dir.begin(), dir.end()) + textureFilename; //D3DXCreateTextureFromFile() //D3DxCreateTexture HRESULT result = D3DXCreateTexture(graphicsDevice, tileWidth, tileHeight, 1, D3DPOOL_DEFAULT, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, &extractedTexture); if (result != S_OK) return false; LPDIRECT3DSURFACE9 t; extractedTexture->GetSurfaceLevel(0, &t); D3DXLoadSurfaceFromSurface(t, NULL, NULL, extractedSurface, NULL, NULL, D3DX_FILTER_NONE, 0); // ADD IT TO THE STRING TABLE wstringTable.putWStringInTable(textureFilename); // AND ADD IT TO THE TEXTURES textures[textureFilename] = extractedTexture; extractedSurface->Release(); t->Release(); } } surfaceToDivide->Release(); textureToDivide->Release(); return true; }
//////////////////////////////////////////////////////////////// // // CPixelsManager::SetTexturePixels // // Copy pixels into texture // //////////////////////////////////////////////////////////////// bool CPixelsManager::SetTexturePixels ( IDirect3DBaseTexture9* pD3DBaseTexture, const CPixels& pixels, const RECT* pRect, uint uiSurfaceIndex ) { if ( !pD3DBaseTexture ) return false; IDirect3DSurface9* pD3DSurface = NULL; CAutoReleaseMe < IDirect3DSurface9 > Thanks( pD3DSurface ); D3DRESOURCETYPE resourceType = pD3DBaseTexture->GetType (); if ( resourceType == D3DRTYPE_VOLUMETEXTURE ) { return SetVolumeTexturePixels ( (IDirect3DVolumeTexture9*)pD3DBaseTexture, pixels, pRect, uiSurfaceIndex ); } else if ( resourceType == D3DRTYPE_CUBETEXTURE ) { D3DCUBEMAP_FACES FaceType = (D3DCUBEMAP_FACES)uiSurfaceIndex; ((IDirect3DCubeTexture9*)pD3DBaseTexture)->GetCubeMapSurface ( FaceType, 0, &pD3DSurface ); if ( !pD3DSurface ) return false; } else if ( resourceType == D3DRTYPE_TEXTURE ) { ((IDirect3DTexture9*)pD3DBaseTexture)->GetSurfaceLevel ( 0, &pD3DSurface ); if ( !pD3DSurface ) return false; } bool bResult = false; D3DSURFACE_DESC Desc; pD3DSurface->GetDesc ( &Desc ); if ( Desc.Usage == D3DUSAGE_RENDERTARGET ) { // Get pixels onto offscreen surface IDirect3DSurface9* pLockableSurface = GetRTLockableSurface ( pD3DSurface ); // Then bResult = SetSurfacePixels ( pLockableSurface, pixels, pRect ); // And write back if ( bResult ) if ( FAILED ( D3DXLoadSurfaceFromSurface ( pD3DSurface, NULL, NULL, pLockableSurface, NULL, NULL, D3DX_FILTER_NONE, 0 ) ) ) return false; } else if ( Desc.Usage == 0 ) { if ( Desc.Format == D3DFMT_A8R8G8B8 || Desc.Format == D3DFMT_X8R8G8B8 || Desc.Format == D3DFMT_R5G6B5 ) { // Direct reading will work here bResult = SetSurfacePixels ( pD3DSurface, pixels, pRect ); } else { // If not a simple format, use D3DX to convert if ( !GetMatchingOffscreenSurface ( pD3DSurface, m_pTempOffscreenSurface, D3DFMT_A8R8G8B8 ) ) return false; if ( FAILED ( D3DXLoadSurfaceFromSurface ( m_pTempOffscreenSurface, NULL, NULL, pD3DSurface, NULL, NULL, D3DX_FILTER_NONE, 0 ) ) ) return false; // Then bResult = SetSurfacePixels ( m_pTempOffscreenSurface, pixels, pRect ); // And write back if ( bResult ) if ( FAILED ( D3DXLoadSurfaceFromSurface ( pD3DSurface, NULL, NULL, m_pTempOffscreenSurface, NULL, NULL, D3DX_FILTER_NONE, 0 ) ) ) return false; } } return bResult; }
//////////////////////////////////////////////////////////////// // // CPixelsManager::GetTexturePixels // // Copy pixels from texture // //////////////////////////////////////////////////////////////// bool CPixelsManager::GetTexturePixels ( IDirect3DBaseTexture9* pD3DBaseTexture, CPixels& outPixels, const RECT* pRect, uint uiSurfaceIndex ) { if ( !pD3DBaseTexture ) return false; IDirect3DSurface9* pD3DSurface = NULL; CAutoReleaseMe < IDirect3DSurface9 > Thanks( pD3DSurface ); D3DRESOURCETYPE resourceType = pD3DBaseTexture->GetType (); if ( resourceType == D3DRTYPE_VOLUMETEXTURE ) { return GetVolumeTexturePixels ( (IDirect3DVolumeTexture9*)pD3DBaseTexture, outPixels, pRect, uiSurfaceIndex ); } else if ( resourceType == D3DRTYPE_CUBETEXTURE ) { D3DCUBEMAP_FACES FaceType = (D3DCUBEMAP_FACES)uiSurfaceIndex; ((IDirect3DCubeTexture9*)pD3DBaseTexture)->GetCubeMapSurface ( FaceType, 0, &pD3DSurface ); if ( !pD3DSurface ) return false; } else if ( resourceType == D3DRTYPE_TEXTURE ) { ((IDirect3DTexture9*)pD3DBaseTexture)->GetSurfaceLevel ( 0, &pD3DSurface ); if ( !pD3DSurface ) return false; } bool bResult = false; D3DSURFACE_DESC Desc; pD3DSurface->GetDesc ( &Desc ); if ( Desc.Usage == D3DUSAGE_RENDERTARGET ) { // Check we are allowed to read the render target bool bAllowScreenUpload = true; CVARS_GET ( "allow_screen_upload", bAllowScreenUpload ); if ( bAllowScreenUpload ) { // Get pixels onto offscreen surface IDirect3DSurface9* pLockableSurface = GetRTLockableSurface ( pD3DSurface ); // Then bResult = GetSurfacePixels ( pLockableSurface, outPixels, pRect ); } else { // If not allowed, return dummy data uint uiPixelsWidth = 32; uint uiPixelsHeight = 32; outPixels.SetSize ( uiPixelsWidth * uiPixelsHeight * XRGB_BYTES_PER_PIXEL + SIZEOF_PLAIN_TAIL ); memset ( outPixels.GetData (), 0xEF, outPixels.GetSize () ); bResult = SetPlainDimensions ( outPixels, uiPixelsWidth, uiPixelsHeight ); } } else if ( Desc.Usage == 0 ) { if ( Desc.Format == D3DFMT_A8R8G8B8 || Desc.Format == D3DFMT_X8R8G8B8 || Desc.Format == D3DFMT_R5G6B5 ) { // Direct reading will work here bResult = GetSurfacePixels ( pD3DSurface, outPixels, pRect ); } else { // If not a simple format, use D3DX to convert if ( !GetMatchingOffscreenSurface ( pD3DSurface, m_pTempOffscreenSurface, D3DFMT_A8R8G8B8 ) ) return false; if ( FAILED ( D3DXLoadSurfaceFromSurface ( m_pTempOffscreenSurface, NULL, NULL, pD3DSurface, NULL, NULL, D3DX_FILTER_NONE, 0 ) ) ) return false; // Then bResult = GetSurfacePixels ( m_pTempOffscreenSurface, outPixels, pRect ); } } return bResult; }
void* CDX9TextureObject::Read( int level, bool bForceUpdateRead ) { ReadyData(); //level currently ignored, read cannot read mipmaps if( m_Texture ) { LPDIRECT3DDEVICE9 pDevice; if( !m_Renderer ) { return NULL; } pDevice = (LPDIRECT3DDEVICE9)m_Renderer->GetAPIDevice(); if( !pDevice ) { return NULL; } int iTextureSize = (GetColorDepth() / 8) * GetWidth() * GetHeight(); // delete the old buffer if our current one is the wrong size if (m_pLocalBuffer && (iTextureSize != m_iLocalBufferSize)) { delete[] m_pLocalBuffer; m_pLocalBuffer = NULL; m_iLocalBufferSize = 0; } // allocate a new buffer if we don't have one if (!m_pLocalBuffer) { m_pLocalBuffer = new unsigned char[iTextureSize]; m_iLocalBufferSize = iTextureSize; } else { // return current buffer if we aren't forcing a read if (!bForceUpdateRead) return m_pLocalBuffer; } //check what kind of a surface it is, we have to get the surface if it's a rendertarget! if( !m_bRenderTarget ) { if( m_Compressed ) { LPDIRECT3DSURFACE9 Src = NULL; m_Texture->GetSurfaceLevel( 0, &Src ); //convert format to argb first LPDIRECT3DSURFACE9 tempSurf = NULL; HRESULT hr = pDevice->CreateOffscreenPlainSurface( GetWidth(), GetHeight(), D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tempSurf, NULL ); if( hr != D3D_OK || tempSurf == NULL || Src == NULL ) { SAFE_RELEASE( Src ); SAFE_RELEASE( tempSurf ); return NULL; } hr = D3DXLoadSurfaceFromSurface( tempSurf, NULL, NULL, Src, NULL, NULL, D3DX_DEFAULT, 0 ); if( hr != D3D_OK ) { return NULL; } //lock the texture and read the data D3DLOCKED_RECT lockrect; hr = tempSurf->LockRect( &lockrect, NULL, D3DLOCK_READONLY ); if( hr == D3D_OK ) { UINT pixelsize = (GetColorDepth()/8); BYTE * srcbits = (BYTE*)lockrect.pBits; BYTE * destbits = (BYTE*)m_pLocalBuffer; //write the texture to the buffer for( UINT i = 0; i < m_Height; i++ ) { memcpy( destbits, srcbits, m_Width*pixelsize ); //move by pitch srcbits += lockrect.Pitch; destbits += m_Width*pixelsize; } } tempSurf->UnlockRect(); SAFE_RELEASE( tempSurf ); SAFE_RELEASE( Src ); return m_pLocalBuffer; } else { //lock the texture and read the data D3DLOCKED_RECT lockrect; HRESULT hr = m_Texture->LockRect( 0, &lockrect, NULL, D3DLOCK_READONLY ); if( hr == D3D_OK ) { UINT pixelsize = (GetColorDepth()/8); BYTE * srcbits = (BYTE*)lockrect.pBits; BYTE * destbits = (BYTE*)m_pLocalBuffer; //write the texture to the buffer for( UINT i = 0; i < m_Height; i++ ) { memcpy( destbits, srcbits, m_Width*pixelsize ); //move by pitch srcbits += lockrect.Pitch; destbits += m_Width*pixelsize; } } m_Texture->UnlockRect( 0 ); return m_pLocalBuffer; } }else//we are render target, need surface { LPDIRECT3DSURFACE9 RenderSurf = NULL; LPDIRECT3DSURFACE9 OffSurf = NULL; m_Texture->GetSurfaceLevel( 0, &RenderSurf ); if( RenderSurf ) { D3DSURFACE_DESC tDesc; m_Texture->GetLevelDesc(0, &tDesc ); if( FAILED(pDevice->CreateOffscreenPlainSurface( tDesc.Width, tDesc.Height, tDesc.Format, D3DPOOL_SYSTEMMEM, &OffSurf, NULL ))) { RenderSurf->Release(); return NULL; } if( FAILED( pDevice->GetRenderTargetData( RenderSurf, OffSurf ) )) { RenderSurf->Release(); OffSurf->Release(); return NULL; } //No need for rendertarget surface anymore RenderSurf->Release(); //lock the texture and read the data D3DLOCKED_RECT lockrect; HRESULT hr = OffSurf->LockRect( &lockrect, NULL, D3DLOCK_READONLY ); if( hr == D3D_OK ) { UINT pixelsize = (GetColorDepth()/8); BYTE * srcbits = (BYTE*)lockrect.pBits; BYTE * destbits = (BYTE*)m_pLocalBuffer; //write the texture to the buffer for( UINT i = 0; i < m_Height; i++ ) { memcpy( destbits, srcbits, m_Width*pixelsize ); //move by pitch srcbits += lockrect.Pitch; destbits += m_Width*pixelsize; } } OffSurf->UnlockRect(); OffSurf->Release(); } return m_pLocalBuffer; } } return NULL; }
int Render(){ HRESULT r; // D3DLOCKED_RECT LockedRect;//locked area of display memory(buffer really) we are drawing to LPDIRECT3DSURFACE8 pBackSurf = 0; if(!g_pDevice){ SetError("Cannot render because there is no device"); return E_FAIL; } //clear the display arera with colour black, ignore stencil buffer g_pDevice->Clear(0,0,D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,25), 1.0f, 0); //get pointer to backbuffer r=g_pDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO, &pBackSurf); if(FAILED(r)){ SetError("Couldn't get backbuffer"); } /* //get a lock on the surface r=pBackSurf->LockRect(&LockedRect, NULL, 0); if(FAILED(r)){ SetError("Could not lock the back buffer"); } DWORD* pData = (DWORD*)(LockedRect.pBits); //DRAW CODE GOES HERE - use pData Draw(LockedRect.Pitch, pData); */ LPDIRECT3DSURFACE8 pSurface = 0; r=LoadBitmapToSurface("baboon.bmp", &pSurface, g_pDevice); if(FAILED(r)){ SetError("could not load bitmap surface"); } D3DSURFACE_DESC d3dsd; pSurface->GetDesc(&d3dsd);//get info about surface POINT DestPoint = {0, 0}; RECT rect = {0,0, d3dsd.Width, d3dsd.Height};//source dimensions // SetError("size x=%d size y=%d format=%d",d3dsd.Width, d3dsd.Height, d3dsd.Format); // r=g_pDevice->CopyRects(pSurface, &rect, 1, pBackSurf, &DestPoint);//copy surface to buffer (like a bitblt) r=D3DXLoadSurfaceFromSurface(pBackSurf, NULL, NULL, pSurface, NULL, &rect, D3DX_FILTER_TRIANGLE,0); // r=D3DXLoadSurfaceFromSurface(pBackSurf, NULL, NULL, pSurface, NULL, &rect, D3DX_FILTER_POINT, 0); if(ERROR(r)) SetError("did not copy surface"); // SimpleBitmapDraw("baboon.bmp", pBackSurf, 10,10); pSurface->Release(); pSurface = 0; // pBackSurf->UnlockRect(); // pData = 0; // pBackSurf->Release();//release lock // pBackSurf = 0; g_pDevice->Present(NULL, NULL, NULL, NULL);//swap over buffer to primary surface return S_OK; }
HRESULT CDxtexDoc::BltAllLevels(D3DCUBEMAP_FACES FaceType, LPDIRECT3DBASETEXTURE9 ptexSrc, LPDIRECT3DBASETEXTURE9 ptexDest) { HRESULT hr; LPDIRECT3DTEXTURE9 pmiptexSrc; LPDIRECT3DTEXTURE9 pmiptexDest; LPDIRECT3DCUBETEXTURE9 pcubetexSrc; LPDIRECT3DCUBETEXTURE9 pcubetexDest; LPDIRECT3DVOLUMETEXTURE9 pvoltexSrc; LPDIRECT3DVOLUMETEXTURE9 pvoltexDest; DWORD iLevel; if (IsVolumeMap()) { pvoltexSrc = (LPDIRECT3DVOLUMETEXTURE9)ptexSrc; pvoltexDest = (LPDIRECT3DVOLUMETEXTURE9)ptexDest; } else if (IsCubeMap()) { pcubetexSrc = (LPDIRECT3DCUBETEXTURE9)ptexSrc; pcubetexDest = (LPDIRECT3DCUBETEXTURE9)ptexDest; } else { pmiptexSrc = (LPDIRECT3DTEXTURE9)ptexSrc; pmiptexDest = (LPDIRECT3DTEXTURE9)ptexDest; } for (iLevel = 0; iLevel < m_numMips; iLevel++) { if (IsVolumeMap()) { LPDIRECT3DVOLUME9 pvolSrc = NULL; LPDIRECT3DVOLUME9 pvolDest = NULL; hr = pvoltexSrc->GetVolumeLevel(iLevel, &pvolSrc); hr = pvoltexDest->GetVolumeLevel(iLevel, &pvolDest); hr = D3DXLoadVolumeFromVolume(pvolDest, NULL, NULL, pvolSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&pvolSrc); ReleasePpo(&pvolDest); } else if (IsCubeMap()) { LPDIRECT3DSURFACE9 psurfSrc = NULL; LPDIRECT3DSURFACE9 psurfDest = NULL; hr = pcubetexSrc->GetCubeMapSurface(FaceType, iLevel, &psurfSrc); hr = pcubetexDest->GetCubeMapSurface(FaceType, iLevel, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); } else { LPDIRECT3DSURFACE9 psurfSrc = NULL; LPDIRECT3DSURFACE9 psurfDest = NULL; hr = pmiptexSrc->GetSurfaceLevel(iLevel, &psurfSrc); hr = pmiptexDest->GetSurfaceLevel(iLevel, &psurfDest); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_DEFAULT, 0); ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); } } return S_OK; }