🔒 Locked
Copy Texture
Advertisement
Original Post
Quote:Nope, that's not correct. Your choices are:
Original post by Antonym
Hello I am trying to copy/clone a texture but I get an error with my code. Is this not the right way to do it?
*** Source Snippet Removed ***
Thanks.
Each of those operate on surfaces, so you'll have to do each one for each surface level in the texture.
However, this isn't usually something you'd want to do (Which is why there's no Duplicate() function or anything). Why do you need two copies of the same texture?
Quote:Ok, that's fair enough (What you're trying to do is commonly called Copy On Write, or COW).
Original post by Antonym
Because if I have two or more objects that use the same texture and I edit one I don't want the other(s) to exhibit the edition too :S.
What memory pool are your textures in? Assuming they're in D3DPOOL_MANAGED (They should be unless they're dynamic really), D3DPOOL_SYSTEMMEM or D3DPOOL_SCRATCH, you'd be best using the LockRect() method.
Untested code:
DWORD GetBytesPerPixelFromFormat(D3DFORMAT fmt){ switch(fmt) { case D3DFMT_R8G8B8: return 3; case D3DFMT_A8R8G8B8: case D3DFMT_X8R8G8B8: case D3DFMT_A2B10G10R10: case D3DFMT_A8B8G8R8: case D3DFMT_X8B8G8R8: case D3DFMT_G16R16: case D3DFMT_A2R10G10B10: case D3DFMT_X8L8V8U8: case D3DFMT_Q8W8V8U8: case D3DFMT_V16U16: case D3DFMT_A2W10V10U10: case D3DFMT_G16R16F: case D3DFMT_R32F: return 4; case D3DFMT_R5G6B5: case D3DFMT_X1R5G5B5: case D3DFMT_A1R5G5B5: case D3DFMT_A4R4G4B4: case D3DFMT_A8R3G3B2: case D3DFMT_X4R4G4B4: case D3DFMT_A8P8: case D3DFMT_A8L8: case D3DFMT_V8U8: case D3DFMT_L6V5U5: case D3DFMT_L16: case D3DFMT_R16F: case D3DFMT_CxV8U8: return 2; case D3DFMT_R3G3B2: case D3DFMT_A8: case D3DFMT_P8: case D3DFMT_L8: case D3DFMT_A4L4: return 1; case D3DFMT_A16B16G16R16: case D3DFMT_Q16W16V16U16: case D3DFMT_A16B16G16R16F: case D3DFMT_G32R32F: return 8; case D3DFMT_A32B32G32R32F: return 16; } // Unknown format return 0;}LPDIRECT3DTEXTURE9 DuplicateTexture(LPDIRECT3DTEXTURE9 pSrc, LPDIRECT3DDEVICE9 pDevice){ // Get number of mip levels and size of top level D3DSURFACE_DESC desc; DWORD dwLevels = pSrc->GetLevelCount(); HRESULT hResult = pSrc->GetLevelDesc(0, &desc); if(FAILED(hResult)) return NULL; DWORD dwBytesPerPixel = GetBytesPerPixelFromFormat(desc.Format); if(dwBytesPerPixel == 0) return NULL; // Create a texture that is the same size LPDIRECT3DTEXTURE9 pDest = NULL; hResult = pDevice->CreateTexture(desc.Width, desc.Height, dwLevels, desc.Usage, desc.Format, desc.Pool, &pDest, NULL); if(FAILED(hResult)) return NULL; // Lock and copy each surface level in turn for(DWORD i=0; i<dwLevels; ++i) { // Lock source texture D3DLOCKED_RECT rectSrc, rectDest; hResult = pSrc->LockRect(i, &rectSrc, NULL, D3DLOCK_READONLY); if(FAILED(hResult)) { pDest->Release(); return NULL; } // Lock destination texture D3DLOCKED_RECT rectDest; hResult = pDest->LockRect(i, &rectDest, NULL, 0); if(FAILED(hResult)) { pSrc->UnlockRect(i); pDest->Release(); return NULL; } // If the pitch is the same as bytes per pixel * width, then we can copy the // entire surface in one go. Otherwise, there's reserved data at the end of // each scanline, and we have to copy a row at a time. if(rectSrc.Pitch == desc.Width*dwBytesPerPixel && rectSrc.Pitch == rectDest.Pitch) { memcpy(rectDest.pBits, rectSrc.pBits, rectSrc.Pitch*desc.Height); } else { DWORD dwBytes = desc.Width*dwBytesPerPixel; for(UINT y=0; y<desc.Height; ++y) { BYTE* pBitsSrc = (BYTE*)rectSrc.pBits + rectSrc.Pitch*y; BYTE* pBitsDest = (BYTE*)rectDest.pBits + rectDest.Pitch*y; memcpy(pBitsDest, pBitsSrc, dwBytes); } } // Copy complete, unlock surfaces pDest->UnlockRect(i); pSrc->UnlockRect(i); } // All levels copied, return newly copied texture return pDest;}Hmm, that took longer to write than I thought...
EDIT: Removed dwLockFlags stuff, that's only valid for default pool textures, which aren't lockable anyway...
[Edited by - Evil Steve on May 25, 2009 8:49:10 AM]
Wow that was fast. Thanks a lot!
Edit: the hResult fails for some reason :S.
This is the code I use to load a texture.
Edit: the hResult fails for some reason :S.
// Lock destination texture hResult = pSrc->LockRect(i, &rectDest, NULL, 0); if(FAILED(hResult)) { pSrc->UnlockRect(i); pDest->Release(); return NULL; }This is the code I use to load a texture.
Sprite* Direct3D::LoadSprite(LPCTSTR fileName, float textureWidth, float textureHeight, float mFrameWidth, float mFrameHeight){ LPDIRECT3DTEXTURE9 texture; D3DXCreateTextureFromFileEx(d3d_device, fileName, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT, 0, //D3DUSAGE_RENDERTARGET? //0 D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, //DEFAULT? //MANAGED D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 0, 255), NULL, NULL, &texture); Sprite *sprite = new Sprite(texture, textureWidth, textureHeight, mFrameWidth, mFrameHeight); return sprite;}Quote:What do the Debug Runtimes say the problem is?
Original post by Antonym
Wow that was fast. Thanks a lot!
Edit: the hResult fails for some reason :S.
Also, that was a typo which I corrected; it should be:
hResult = pDest->Lock(...
EDIT: In fact, that's probably the problem - you can't have two locks on one surface (Or they can't be overlapping regions, I don't recall offhand)
Yeah that was the problem though another one popped up.
The problem occurs at.
The debugger tells me.
The problem occurs at.
DWORD dwBytes = desc.Width*dwBytesPerPixel; for(UINT y=0; y<desc.Height; ++y) { BYTE* pBitsSrc = (BYTE*)rectSrc.pBits + rectSrc.Pitch*y; BYTE* pBitsDest = (BYTE*)rectDest.pBits + rectDest.Pitch*y; memcpy(pBitsDest, pBitsSrc, dwBytes); }The debugger tells me.
Direct3D9: :DoneExclusiveMode'Dungeon.exe': Loaded 'C:\WINDOWS\system32\usp10.dll'First-chance exception at 0x1023fe24 (msvcr90d.dll) in Dungeon.exe: 0xC0000005: Access violation writing location 0x01899000.Unhandled exception at 0x1023fe24 (msvcr90d.dll) in Dungeon.exe: 0xC0000005: Access violation writing location 0x01899000.Quote:What are the values of y and dwBytes when the access violation occurs?
Original post by Antonym
Yeah that was the problem though another one popped up.
The problem occurs at.
*** Source Snippet Removed ***
The debugger tells me.
*** Source Snippet Removed ***
Quote:Interesting. What is desc.Width and desc.Height?
Original post by Antonym
y is 83
dwBytes is 384.
Oh, I see the problem. Change the relevant section of code to the following:
The code was incorrectly assuming all mip levels are the same. if that doesn't fix the problem, what are the values of i and dwLevels?
// Lock and copy each surface level in turn for(DWORD i=0; i<dwLevels; ++i) { // Get size of this level HRESULT hResult = pSrc->GetLevelDesc(i, &desc); if(FAILED(hResult)) { pDest->Release(); return NULL; } // Lock source texture D3DLOCKED_RECT rectSrc;Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement