// interface functions void MFTexture_CreatePlatformSpecific(MFTexture *pTexture, bool generateMipChain) { MFTextureTemplateData *pTemplate = pTexture->pTemplateData; // create texture D3DFORMAT platformFormat = (D3DFORMAT)MFTexture_GetPlatformFormatID(pTemplate->imageFormat, MFDD_XBOX); #if defined(XB_XGTEXTURES) pTexture->pTexture = &pTexture->texture; XGSetTextureHeader(pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, 1, 0, platformFormat, 0, pTexture->pTexture, 0, 0); pTexture->pTexture->Register(pTemplate->pSurfaces[0].pImageData); if(pTemplate->imageFormat >= TexFmt_XB_A8R8G8B8s && pTemplate->imageFormat <= TexFmt_XB_R4G4B4A4s) { XGSwizzleRect(pTemplate->pSurfaces[0].pImageData, 0, NULL, pTemplate->pSurfaces[0].pImageData, pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, NULL, pTemplate->pSurfaces[0].bitsPerPixel/8); } #else HRESULT hr; hr = D3DXCreateTexture(pd3dDevice, pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, generateMipChain ? 0 : 1, 0, platformFormat, 0, &pTexture->pTexture); MFDebug_Assert(hr != D3DERR_NOTAVAILABLE, MFStr("LoadTexture failed: D3DERR_NOTAVAILABLE, 0x%08X", hr)); MFDebug_Assert(hr != D3DERR_OUTOFVIDEOMEMORY, MFStr("LoadTexture failed: D3DERR_OUTOFVIDEOMEMORY, 0x%08X", hr)); MFDebug_Assert(hr != D3DERR_INVALIDCALL, MFStr("LoadTexture failed: D3DERR_INVALIDCALL, 0x%08X", hr)); MFDebug_Assert(hr != D3DXERR_INVALIDDATA, MFStr("LoadTexture failed: D3DXERR_INVALIDDATA, 0x%08X", hr)); MFDebug_Assert(hr == D3D_OK, MFStr("Failed to create texture '%s'.", pTexture->name)); // copy image data D3DLOCKED_RECT rect; pTexture->pTexture->LockRect(0, &rect, NULL, 0); if(pTemplate->imageFormat >= TexFmt_XB_A8R8G8B8s && pTemplate->imageFormat <= TexFmt_XB_R4G4B4A4s) { XGSwizzleRect(pTemplate->pSurfaces[0].pImageData, 0, NULL, rect.pBits, pTemplate->pSurfaces[0].width, pTemplate->pSurfaces[0].height, NULL, pTemplate->pSurfaces[0].bitsPerPixel/8); } else { MFCopyMemory(rect.pBits, pTemplate->pSurfaces[0].pImageData, pTemplate->pSurfaces[0].bufferLength); } pTexture->pTexture->UnlockRect(0); // filter mip levels if(generateMipChain) D3DXFilterTexture(pTexture->pTexture, NULL, 0, D3DX_DEFAULT); #endif }
void RageDisplay_D3D::UpdateTexture( unsigned uTexHandle, RageSurface* img, int xoffset, int yoffset, int width, int height ) { IDirect3DTexture9* pTex = (IDirect3DTexture9*)uTexHandle; ASSERT( pTex != NULL ); RECT rect; rect.left = xoffset; rect.top = yoffset; rect.right = width - xoffset; rect.bottom = height - yoffset; D3DLOCKED_RECT lr; pTex->LockRect( 0, &lr, &rect, 0 ); D3DSURFACE_DESC desc; pTex->GetLevelDesc(0, &desc); ASSERT( xoffset+width <= int(desc.Width) ); ASSERT( yoffset+height <= int(desc.Height) ); // // Copy bits // #if defined(XBOX) // Xbox textures need to be swizzled XGSwizzleRect( img->pixels, // pSource, img->pitch, // Pitch, NULL, // pRect, lr.pBits, // pDest, img->w, // Width, img->h, // Height, NULL, // pPoint, img->format->BytesPerPixel ); //BytesPerPixel #else int texpixfmt; for(texpixfmt = 0; texpixfmt < NUM_PIX_FORMATS; ++texpixfmt) if(D3DFORMATS[texpixfmt] == desc.Format) break; ASSERT( texpixfmt != NUM_PIX_FORMATS ); RageSurface *Texture = CreateSurfaceFromPixfmt(RagePixelFormat(texpixfmt), lr.pBits, width, height, lr.Pitch); ASSERT( Texture ); RageSurfaceUtils::Blit( img, Texture, width, height ); delete Texture; #endif pTex->UnlockRect( 0 ); }
//----------------------------------------------------------------------------- // Name: XBUtil_SwizzleTexture2D() // Desc: Swizzles a 2D texture before it gets unlocked. Note: this operation // can be very slow. //----------------------------------------------------------------------------- VOID XBUtil_SwizzleTexture2D( D3DLOCKED_RECT* pLock, const D3DSURFACE_DESC* pDesc ) { DWORD dwPixelSize = XGBytesPerPixelFromFormat( pDesc->Format ); DWORD dwTextureSize = pDesc->Width * pDesc->Height * dwPixelSize; BYTE* pSrcBits = new BYTE[ dwTextureSize ]; memcpy( pSrcBits, pLock->pBits, dwTextureSize ); XGSwizzleRect( pSrcBits, 0, NULL, pLock->pBits, pDesc->Width, pDesc->Height, NULL, dwPixelSize ); SAFE_DELETE_ARRAY( pSrcBits ); }
void Font::RenderToTexture(CSurface &texture, const string &str, dword height, dword style, D3DXCOLOR color, int maxWidth, bool fade) { xdk_d3d_video_t *d3d = (xdk_d3d_video_t*)driver.video_data; if (m_pFont == NULL) return; m_pFont->SetTextHeight(height); m_pFont->SetTextStyle(style); m_pFont->SetTextColor(color); dword dwMaxWidth = (maxWidth <= 0) ? 1000 : maxWidth; // get the exact width and height required to display the string dword dwRequiredWidth = GetRequiredWidth(str, height, style); dword dwRequiredHeight = GetRequiredHeight(str, height, style);; // calculate the texture width and height needed to display the font dword dwTextureWidth = dwRequiredWidth * 2; dword dwTextureHeight = dwRequiredHeight * 2; { // because the textures are swizzled we make sure // the dimensions are a power of two for(dword wmask = 1; dwTextureWidth &(dwTextureWidth - 1); wmask = (wmask << 1 ) + 1) dwTextureWidth = (dwTextureWidth + wmask) & ~wmask; for(dword hmask = 1; dwTextureHeight &(dwTextureHeight - 1); hmask = (hmask << 1) + 1) dwTextureHeight = ( dwTextureHeight + hmask ) & ~hmask; // also enforce a minimum pitch of 64 bytes dwTextureWidth = max(64 / XGBytesPerPixelFromFormat(D3DFMT_A8R8G8B8), dwTextureWidth); } // create an temporary image surface to render to D3DSurface *pTempSurface; d3d->d3d_render_device->CreateImageSurface(dwTextureWidth, dwTextureHeight, D3DFMT_LIN_A8R8G8B8, &pTempSurface); // clear the temporary surface { D3DLOCKED_RECT tmpLr; pTempSurface->LockRect(&tmpLr, NULL, 0); memset(tmpLr.pBits, 0, dwTextureWidth * dwTextureHeight * XGBytesPerPixelFromFormat(D3DFMT_A8R8G8B8)); pTempSurface->UnlockRect(); } // render the text to the temporary surface word *wcBuf = StringToWChar(str); m_pFont->TextOut(pTempSurface, wcBuf, -1, 0, 0); delete [] wcBuf; // create the texture that will be drawn to the screen texture.Destroy(); texture.Create(dwTextureWidth, dwTextureHeight); // copy from the temporary surface to the final texture { D3DLOCKED_RECT tmpLr; D3DLOCKED_RECT txtLr; pTempSurface->LockRect(&tmpLr, NULL, 0); texture.GetTexture()->LockRect(0, &txtLr, NULL, 0); if (fade) { // draw the last 35 pixels of the string fading out to max width or texture width dword dwMinFadeDistance = min(static_cast<dword>(dwTextureWidth * 0.35), 35); dword dwFadeStart = min(dwTextureWidth, dwMaxWidth - dwMinFadeDistance); dword dwFadeEnd = min(dwTextureWidth, dwMaxWidth); dword dwFadeDistance = dwFadeEnd - dwFadeStart; for (dword h = 0; h < dwTextureHeight; h++) { for (dword w = 0; w < dwFadeDistance; w++) { dword *pColor = reinterpret_cast<dword *>(tmpLr.pBits); dword offset = (h * dwTextureWidth) + (dwFadeStart + w); D3DXCOLOR color = D3DXCOLOR(pColor[offset]); color.a = color.a * (1.0f - static_cast<float>(w) / static_cast<float>(dwFadeDistance)); pColor[offset] = color; } } } // dont draw anything > than max width for (dword h = 0; h < dwTextureHeight; h++) { for (dword w = min(dwTextureWidth, dwMaxWidth); w < dwTextureWidth; w++) { dword *pColor = reinterpret_cast<dword *>(tmpLr.pBits); dword offset = (h * dwTextureWidth) + w; D3DXCOLOR color = D3DXCOLOR(pColor[offset]); color.a = 0.0; pColor[offset] = color; } } // copy and swizzle the linear surface to the swizzled texture XGSwizzleRect(tmpLr.pBits, tmpLr.Pitch, NULL, txtLr.pBits, dwTextureWidth, dwTextureHeight, NULL, 4); texture.GetTexture()->UnlockRect(0); pTempSurface->UnlockRect(); } pTempSurface->Release(); }
//----------------------------------------------------------------------------- // Name: XBUtil_CreateNormalizationCubeMap() // Desc: Creates a cubemap and fills it with normalized RGBA vectors //----------------------------------------------------------------------------- HRESULT XBUtil_CreateNormalizationCubeMap( LPDIRECT3DDEVICE8 pd3dDevice, DWORD dwSize, LPDIRECT3DCUBETEXTURE8* ppCubeMap ) { HRESULT hr; // Create the cube map if( FAILED( hr = pd3dDevice->CreateCubeTexture( dwSize, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, ppCubeMap ) ) ) return E_FAIL; // Allocate temp space for swizzling the cubemap surfaces DWORD* pSourceBits = new DWORD[ dwSize * dwSize ]; // Fill all six sides of the cubemap for( DWORD i=0; i<6; i++ ) { // Lock the i'th cubemap surface LPDIRECT3DSURFACE8 pCubeMapFace; (*ppCubeMap)->GetCubeMapSurface( (D3DCUBEMAP_FACES)i, 0, &pCubeMapFace ); // Write the RGBA-encoded normals to the surface pixels DWORD* pPixel = pSourceBits; D3DXVECTOR3 n; FLOAT w, h; for( DWORD y = 0; y < dwSize; y++ ) { h = (FLOAT)y / (FLOAT)(dwSize-1); // 0 to 1 h = ( h * 2.0f ) - 1.0f; // -1 to 1 for( DWORD x = 0; x < dwSize; x++ ) { w = (FLOAT)x / (FLOAT)(dwSize-1); // 0 to 1 w = ( w * 2.0f ) - 1.0f; // -1 to 1 // Calc the normal for this texel switch( i ) { case D3DCUBEMAP_FACE_POSITIVE_X: // +x n.x = +1.0; n.y = -h; n.z = -w; break; case D3DCUBEMAP_FACE_NEGATIVE_X: // -x n.x = -1.0; n.y = -h; n.z = +w; break; case D3DCUBEMAP_FACE_POSITIVE_Y: // y n.x = +w; n.y = +1.0; n.z = +h; break; case D3DCUBEMAP_FACE_NEGATIVE_Y: // -y n.x = +w; n.y = -1.0; n.z = -h; break; case D3DCUBEMAP_FACE_POSITIVE_Z: // +z n.x = +w; n.y = -h; n.z = +1.0; break; case D3DCUBEMAP_FACE_NEGATIVE_Z: // -z n.x = -w; n.y = -h; n.z = -1.0; break; } // Store the normal as an RGBA color D3DXVec3Normalize( &n, &n ); *pPixel++ = XBUtil_VectorToRGBA( &n ); } } // Swizzle the result into the cubemap face surface D3DLOCKED_RECT lock; pCubeMapFace->LockRect( &lock, 0, 0L ); XGSwizzleRect( pSourceBits, 0, NULL, lock.pBits, dwSize, dwSize, NULL, sizeof(DWORD) ); pCubeMapFace->UnlockRect(); // Release the cubemap face pCubeMapFace->Release(); } // Free temp space SAFE_DELETE_ARRAY( pSourceBits ); return S_OK; }