//! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture void CD3D8Texture::regenerateMipMapLevels(void* mipmapData) { if (mipmapData) { core::dimension2du size = TextureSize; u32 level=0; do { if (size.Width>1) size.Width /=2; if (size.Height>1) size.Height /=2; ++level; IDirect3DSurface8* mipSurface = 0; HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); if (FAILED(hr) || !mipSurface) { os::Printer::log("Could not get mipmap level", ELL_WARNING); return; } D3DSURFACE_DESC mipDesc; mipSurface->GetDesc(&mipDesc); D3DLOCKED_RECT miplr; // lock mipmap surface if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) { mipSurface->Release(); os::Printer::log("Could not lock texture", ELL_WARNING); return; } memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; // unlock mipSurface->UnlockRect(); // release mipSurface->Release(); } while (size.Width != 1 || size.Height != 1); } else if (HasMipMaps) { // create mip maps. #ifndef _IRR_USE_D3DXFilterTexture_ // The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when // compiling with both D3D 8 and 9. HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT , D3DX_DEFAULT ); if (FAILED(hr)) #endif createMipMaps(); } }
RageSurface* RageDisplay_D3D::CreateScreenshot() { #if defined(XBOX) return NULL; #else /* Get the back buffer. */ IDirect3DSurface8* pSurface; g_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pSurface ); /* Get the back buffer description. */ D3DSURFACE_DESC desc; pSurface->GetDesc( &desc ); /* Copy the back buffer into a surface of a type we support. */ IDirect3DSurface8* pCopy; g_pd3dDevice->CreateImageSurface( desc.Width, desc.Height, D3DFMT_A8R8G8B8, &pCopy ); D3DXLoadSurfaceFromSurface( pCopy, NULL, NULL, pSurface, NULL, NULL, D3DX_DEFAULT, 0 ); pSurface->Release(); /* Update desc from the copy. */ pCopy->GetDesc( &desc ); D3DLOCKED_RECT lr; { RECT rect; rect.left = 0; rect.top = 0; rect.right = desc.Width; rect.bottom = desc.Height; pCopy->LockRect( &lr, &rect, D3DLOCK_READONLY ); } RageSurface *surface = CreateSurfaceFromPixfmt( FMT_RGBA8, lr.pBits, desc.Width, desc.Height, lr.Pitch); ASSERT( surface ); /* We need to make a copy, since lr.pBits will go away when we call UnlockRect(). */ RageSurface *SurfaceCopy = CreateSurface( surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask ); RageSurfaceUtils::CopySurface( surface, SurfaceCopy ); delete surface; pCopy->UnlockRect(); pCopy->Release(); return SurfaceCopy; #endif }
RageSurface* RageDisplay_D3D::CreateScreenshot() { // Get the back buffer. IDirect3DSurface8* pSurface; g_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pSurface ); // Get the back buffer description. D3DSURFACE_DESC desc; pSurface->GetDesc( &desc ); // Copy the back buffer into a surface of a type we support. IDirect3DSurface8* pCopy; g_pd3dDevice->CreateImageSurface( desc.Width, desc.Height, D3DFMT_A8R8G8B8, &pCopy ); // Aldo_MX: D3DXLoadSurfaceFromSurface requires d3dx8core.h, I replaced it with CopyRects to // remove this dependency so its possible to compile SM with any DirectX SDK up to Aug 2007 D3DXLoadSurfaceFromSurface( pCopy, NULL, NULL, pSurface, NULL, NULL, D3DX_DEFAULT, 0 ); //g_pd3dDevice->CopyRects( pSurface, NULL, 0, pCopy, NULL ); pSurface->Release(); // Update desc from the copy. pCopy->GetDesc( &desc ); D3DLOCKED_RECT lr; { RECT rect; rect.left = 0; rect.top = 0; rect.right = desc.Width; rect.bottom = desc.Height; pCopy->LockRect( &lr, &rect, D3DLOCK_READONLY ); } RageSurface *surface = CreateSurfaceFromPixfmt( PixelFormat_RGBA8, lr.pBits, desc.Width, desc.Height, lr.Pitch); ASSERT( surface ); // We need to make a copy, since lr.pBits will go away when we call UnlockRect(). RageSurface *SurfaceCopy = CreateSurface( surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask ); RageSurfaceUtils::CopySurface( surface, SurfaceCopy ); delete surface; pCopy->UnlockRect(); pCopy->Release(); return SurfaceCopy; }
static void d3d8_shmem_capture_copy(int idx) { IDirect3DSurface8 *target = data.copy_surfaces[idx]; D3DLOCKED_RECT rect; HRESULT hr; if (data.surface_locked[idx]) return; hr = target->LockRect(&rect, nullptr, D3DLOCK_READONLY); if (SUCCEEDED(hr)) { shmem_copy_data(idx, rect.pBits); } }
// The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when // compiling with both D3D 8 and 9. bool CD3D8Texture::createMipMaps(u32 level) { if (level==0) return true; IDirect3DSurface8* upperSurface = 0; IDirect3DSurface8* lowerSurface = 0; // get upper level HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface); if (FAILED(hr) || !upperSurface) { os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING); return false; } // get lower level hr = Texture->GetSurfaceLevel(level, &lowerSurface); if (FAILED(hr) || !lowerSurface) { os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING); upperSurface->Release(); return false; } D3DSURFACE_DESC upperDesc, lowerDesc; upperSurface->GetDesc(&upperDesc); lowerSurface->GetDesc(&lowerDesc); D3DLOCKED_RECT upperlr; D3DLOCKED_RECT lowerlr; // lock upper surface if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0))) { os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING); upperSurface->Release(); lowerSurface->Release(); return false; } // lock lower surface if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0))) { os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING); upperSurface->UnlockRect(); upperSurface->Release(); lowerSurface->Release(); return false; } if (upperDesc.Format != lowerDesc.Format) { os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING); } else { if (upperDesc.Format == D3DFMT_A1R5G5B5) copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else if (upperDesc.Format == D3DFMT_A8R8G8B8) copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING); } bool result=true; // unlock if (FAILED(upperSurface->UnlockRect())) result=false; if (FAILED(lowerSurface->UnlockRect())) result=false; // release upperSurface->Release(); lowerSurface->Release(); if (!result || upperDesc.Width < 3 || upperDesc.Height < 3) return result; // stop generating levels // generate next level return createMipMaps(level+1); }
IDirect3DSurface8* loadBitmap(LPCSTR filename, D3DFORMAT format) { //Comme d'habitude on va utiliser GDI, donc on commence par créer un DC HDC hdc = CreateCompatibleDC ( NULL ) ; //ensuite on peut charger l'image HBITMAP hbmNew = ( HBITMAP ) LoadImage ( NULL , filename, IMAGE_BITMAP , 0 , 0 , LR_LOADFROMFILE ) ; //on récupère les dimensions de l'image BITMAP bmp ; GetObject ( hbmNew , sizeof ( BITMAP ) , &bmp ); //et on sélectionne l'image dans notre dc HBITMAP hbmOld = ( HBITMAP ) SelectObject ( hdc , hbmNew ) ; //nous pouvons maintenant créer l'image surface pour D3D en spécifiante la taille de l'image IDirect3DSurface8* pSurface ; if (FAILED(_dd3dInter->CreateImageSurface ( bmp.bmWidth , bmp.bmHeight , format , &pSurface ))) MessageBox(NULL, "erreur", "erreur", MB_OK); //on récupère les formats pour chaque couleur DWORD dwRShiftL = 8 - GetFormatRBits ( format ) ; DWORD dwGShiftL = 8 - GetFormatGBits ( format ) ; DWORD dwBShiftL = 8 - GetFormatBBits ( format ) ; DWORD dwRShiftR = GetFormatGBits ( format ) + GetFormatBBits ( format ) ; DWORD dwGShiftR = GetFormatBBits ( format ) ; //nous pouvons maintenant calculer les bits par pixel DWORD dwBytesPerPixel = ( GetFormatXBits ( format ) + GetFormatABits ( format ) + GetFormatRBits ( format ) + GetFormatGBits ( format ) + GetFormatBBits ( format ) ) / 8 ; //quelques variables... COLORREF crColor ; DWORD dwColor ; DWORD dwRed ; DWORD dwGreen ; DWORD dwBlue ; DWORD dwPosition; //nous avons tout ce qu'il faut maintenant pour remplir notre surface D3DLOCKED_RECT lockrect ; pSurface->LockRect ( &lockrect , NULL , 0 ) ; BYTE* pbyBuffer = ( BYTE* ) lockrect.pBits ; //on scanne l'image... for ( int y = 0 ; y < bmp.bmHeight ; y ++ ) { for ( int x = 0 ; x < bmp.bmWidth ; x ++ ) { //récupération du pixel crColor = GetPixel ( hdc , x , y ) ; //calcule de sa position dwPosition = y * lockrect.Pitch + x * dwBytesPerPixel ; //récupération des couleurs dwRed = GetRValue ( crColor ) ; dwGreen = GetGValue ( crColor ) ; dwBlue = GetBValue ( crColor ) ; //convertions.. dwRed >>= dwRShiftL ; dwGreen >>= dwGShiftL ; dwBlue >>= dwBShiftL ; dwRed <<=dwRShiftR ; dwGreen <<=dwGShiftR ; dwColor = dwRed | dwGreen | dwBlue ; //nous pouvons enfin copier le pixel memcpy ( &pbyBuffer [ dwPosition ] , &dwColor , dwBytesPerPixel ) ; } } //unlock la surface pSurface->UnlockRect ( ) ; //restoration du DC SelectObject ( hdc , hbmOld ) ; //destruction de la bitmap DeleteObject ( hbmNew ) ; //destruction du dc DeleteDC ( hdc ) ; //retour du pointeur sur la surface créée return ( pSurface ) ; }