void ReplaceBootTexture(IDirect3DTexture8* srcTexture, IDirect3DTexture8* repTexture, UINT width) { IDirect3DSurface8* src = NULL; IDirect3DSurface8* dest = NULL; RECT destRect; RECT srcRect = {0,0,170,256}; if (width == 512) { destRect.top=0; destRect.left=0; destRect.bottom=256; destRect.right=170; } else { destRect.top=0; destRect.left=0; destRect.bottom=64; destRect.right=170/4; } if (SUCCEEDED(srcTexture->GetSurfaceLevel(0, &dest))) { if (SUCCEEDED(repTexture->GetSurfaceLevel(0, &src))) { // need 3 copies of the boot texture for (int i=0; i<3; i++) { destRect.left = (width==512) ? (i*170) : (i*170/4); destRect.right = (width==512) ? ((i+1)*170) : ((i+1)*170/4); if (SUCCEEDED(D3DXLoadSurfaceFromSurface( dest, NULL, &destRect, src, NULL, &srcRect, D3DX_DEFAULT, 0))) { } else { } } src->Release(); } dest->Release(); } }
//! 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 bool d3d8_init_format_backbuffer(IDirect3DDevice8 *device) { IDirect3DSurface8 *backbuffer; D3DSURFACE_DESC desc; HRESULT hr; if (!d3d8_get_window_handle(device)) return false; backbuffer = d3d8_get_backbuffer(device); if (!backbuffer) return false; hr = backbuffer->GetDesc(&desc); backbuffer->Release(); if (FAILED(hr)) { hlog_hr("d3d8_init_format_backbuffer: Failed to get " "backbuffer descriptor", hr); return false; } data.d3d8_format = desc.Format; data.dxgi_format = d3d8_to_dxgi_format(desc.Format); data.cx = desc.Width; data.cy = desc.Height; return true; }
//! lock function void* CD3D8Texture::lock(bool readOnly, u32 mipmapLevel) { if (!Texture) return 0; MipLevelLocked=mipmapLevel; HRESULT hr; D3DLOCKED_RECT rect; if(!IsRenderTarget) { hr = Texture->LockRect(mipmapLevel, &rect, 0, readOnly?D3DLOCK_READONLY:0); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); return 0; } } else { if (!RTTSurface) { // Make RTT surface large enough for all miplevels (including 0) D3DSURFACE_DESC desc; Texture->GetLevelDesc(0, &desc); hr = Device->CreateImageSurface(desc.Width, desc.Height, desc.Format, &RTTSurface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); return 0; } } IDirect3DSurface8 *surface = 0; hr = Texture->GetSurfaceLevel(mipmapLevel, &surface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", "Could not get surface.", ELL_ERROR); return 0; } hr = Device->CopyRects(surface, 0, 0, RTTSurface, 0); surface->Release(); if(FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", "Data copy failed.", ELL_ERROR); return 0; } hr = RTTSurface->LockRect(&rect, 0, readOnly?D3DLOCK_READONLY:0); if(FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", "LockRect failed.", ELL_ERROR); return 0; } } return rect.pBits; }
//! lock function void* CD3D8Texture::lock(bool readOnly) { if (!Texture) return 0; HRESULT hr; D3DLOCKED_RECT rect; if(!IsRenderTarget) { hr = Texture->LockRect(0, &rect, 0, readOnly?D3DLOCK_READONLY:0); } else { D3DSURFACE_DESC desc; Texture->GetLevelDesc(0, &desc); if (!RTTSurface) { hr = Device->CreateImageSurface(desc.Width, desc.Height, desc.Format, &RTTSurface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); return 0; } } IDirect3DSurface8 *surface = 0; hr = Texture->GetSurfaceLevel(0, &surface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); return 0; } hr = Device->CopyRects(surface, 0, 0, RTTSurface, 0); surface->Release(); if(FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); return 0; } hr = RTTSurface->LockRect(&rect, 0, readOnly?D3DLOCK_READONLY:0); if(FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); return 0; } return rect.pBits; } if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); return 0; } return rect.pBits; }
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(); } }
//! Returns pointer to the render target surface IDirect3DSurface8* CD3D8Texture::getRenderTargetSurface() { if (!IsRenderTarget) return 0; IDirect3DSurface8 *pRTTSurface = 0; if (Texture) Texture->GetSurfaceLevel(0, &pRTTSurface); if (pRTTSurface) pRTTSurface->Release(); return pRTTSurface; }
void CD3D8Texture::createRenderTarget() { TextureSize.Width = getTextureSizeFromSurfaceSize(TextureSize.Width); TextureSize.Height = getTextureSizeFromSurfaceSize(TextureSize.Height); // get backbuffer format to create the render target in the // same format IDirect3DSurface8* bb; D3DFORMAT d3DFormat = D3DFMT_A8R8G8B8; if (!FAILED(Device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &bb))) { D3DSURFACE_DESC desc; bb->GetDesc(&desc); d3DFormat = desc.Format; if (d3DFormat == D3DFMT_X8R8G8B8) d3DFormat = D3DFMT_A8R8G8B8; bb->Release(); } else { os::Printer::log("Could not create RenderTarget texture: could not get BackBuffer.", ELL_WARNING); return; } // create texture HRESULT hr; hr = Device->CreateTexture( TextureSize.Width, TextureSize.Height, 1, // mip map level count, we don't want mipmaps here D3DUSAGE_RENDERTARGET, d3DFormat, D3DPOOL_DEFAULT, &Texture); // get irrlicht format from D3D format ColorFormat = getColorFormatFromD3DFormat(d3DFormat); if (FAILED(hr)) os::Printer::log("Could not create render target texture"); }
static HRESULT STDMETHODCALLTYPE hook_present(IDirect3DDevice8 *device, CONST RECT *src_rect, CONST RECT *dst_rect, HWND override_window, CONST RGNDATA *dirty_region) { IDirect3DSurface8 *backbuffer; HRESULT hr; backbuffer = d3d8_get_backbuffer(device); if (backbuffer) { d3d8_capture(device, backbuffer); backbuffer->Release(); } unhook(&present); present_t call = (present_t)present.call_addr; hr = call(device, src_rect, dst_rect, override_window, dirty_region); rehook(&present); return hr; }
//-- Render ------------------------------------------------------------------- // //----------------------------------------------------------------------------- void ShadeWorm_c::Render() { static State_e state = STATE_NEWCOL; static int fadeCol = 0; IDirect3DSurface8* oldSurface; IDirect3DSurface8* newSurface; m_device->GetRenderTarget(&oldSurface); oldSurface->Release(); m_bufferTexture->GetSurfaceLevel(0, &newSurface); m_device->SetRenderTarget(newSurface, NULL); newSurface->Release(); if (state == STATE_NEWCOL) { if (m_randomColMap) { int newCol = rand() % m_numColMaps; if (newCol == m_colMap) m_colMap = (m_colMap+1) % m_numColMaps; else m_colMap = newCol; } else { m_colMap = (m_colMap+1) % m_numColMaps; } CreateColMap(m_colMap); m_device->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0,0,0), 1.0f, 0L ); float x = 256.0f + (100 - (rand() % 200)); float y = 256.0f + (100 - (rand() % 200)); for (int i = 0; i < m_numWorms; i++) { m_worms[i].vx = 0; m_worms[i].vy = 0; m_worms[i].x = x; m_worms[i].y = y; } state = STATE_FADEUP; m_timer = 60 * m_drawTime; } d3dSetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); d3dSetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); d3dSetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); d3dSetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); d3dSetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); d3dSetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); d3dSetRenderState(D3DRS_ALPHABLENDENABLE, true); d3dSetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); d3dSetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); d3dSetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); d3dSetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); d3dSetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); d3dSetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); d3dSetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); if (state == STATE_FADEDOWN || state == STATE_DRAWING) { for (int i = 0; i < m_numWorms; i++) { m_worms[i].vx += GetRand(); Clamp(-1, 1, m_worms[i].vx); m_worms[i].vy += GetRand(); Clamp(-1, 1, m_worms[i].vy); m_worms[i].x += m_worms[i].vx; Clamp(0, 512, m_worms[i].x); m_worms[i].y += m_worms[i].vy; Clamp(0, 512, m_worms[i].y); } m_device->SetTexture(0, m_spriteTexture); for (int i = 0; i < m_numWorms; i++) RenderSprite(m_worms[i].x , m_worms[i].y, 5, 5, 0x05ffffff); } if (state == STATE_FADEUP) { fadeCol += 0x08; if (fadeCol >= 0xff) { fadeCol = 0xff; state = STATE_DRAWING; } } else if (state == STATE_FADEDOWN) { fadeCol -= 0x08; if (fadeCol <= 0) { fadeCol = 0; state = STATE_NEWCOL; } } else if (state == STATE_DRAWING) { m_timer--; if (m_timer <= 0) state = STATE_FADEDOWN; } d3dSetRenderState(D3DRS_ALPHABLENDENABLE, false); m_device->SetRenderTarget(oldSurface, NULL); m_device->SetTexture(0, m_bufferTexture); m_device->SetTexture(1, m_colMapTexture); d3dSetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_POINT); d3dSetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_POINT); d3dSetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); d3dSetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); m_device->SetPixelShader(m_pShader); float size = fadeCol / 255.0f; RenderSprite(m_width/2.0f, m_height/2.0f, m_width/(2.0f * size), m_height/(2.0f * size), fadeCol << 24); m_device->SetPixelShader(0); m_device->SetTexture(0, NULL); m_device->SetTexture(1, NULL); } // Render
// 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); }