TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) { mTexture = NULL; for (int i = 0; i < 6; ++i) { mRenderTarget[i] = NULL; } // if the size is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation if (size > 0) { IDirect3DDevice9 *device = mRenderer->getDevice(); int height = size; gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); gl::error(GL_OUT_OF_MEMORY); } } initializeRenderTarget(); }
TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) : TextureStorage9(renderer, GetTextureUsage(internalformat, Renderer9::makeRenderer9(renderer), renderTarget)) { mTexture = NULL; for (int i = 0; i < 6; ++i) { mRenderTarget[i] = NULL; } // if the size is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation if (size > 0) { IDirect3DDevice9 *device = mRenderer->getDevice(); int height = size; D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat, mRenderer); d3d9::MakeValidSize(false, format, &size, &height, &mTopLevel); UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); gl::error(GL_OUT_OF_MEMORY); } } initializeRenderTarget(); }
//---------------------------------------------------------------------------- PdrTextureCube::PdrTextureCube (Renderer* renderer, const TextureCube* texture) { IDirect3DDevice9* device = renderer->mData->mDevice; int numLevels = texture->GetNumLevels(); HRESULT hr = device->CreateCubeTexture((UINT)texture->GetWidth(), (UINT)numLevels, gDX9BufferUsage[texture->GetUsage()], gDX9TextureFormat[texture->GetFormat()], D3DPOOL_MANAGED, &mTexture, 0); PX2_UNUSED(hr); assertion(hr == D3D_OK, "Failed to create cube texture: %s\n", DXGetErrorString(hr)); for (int face = 0; face < 6; ++face) { for (int level = 0; level < numLevels; ++level) { void* data = Lock(face, level, Buffer::BL_WRITE_ONLY); memcpy(data, texture->GetData(face, level), texture->GetNumLevelBytes(level)); Unlock(face, level); } } }
TextureDX9::TextureDX9( const PixelFormat texFormat, const TexType texType, const unsigned int sizeX, const unsigned int sizeY, const unsigned int sizeZ, const unsigned int mipmapLevelCount, const BufferUsage usage) : Texture(texFormat, texType, sizeX, sizeY, sizeZ, mipmapLevelCount, usage) , m_pTexture(nullptr) , m_pTempBuffer(nullptr) , m_nRowPitch(0) , m_nDepthPitch(0) { IDirect3DDevice9* device = RendererDX9::GetInstance()->GetDevice(); D3DPOOL pool; if (GetUsage() == BU_TEXTURE) pool = D3DPOOL_MANAGED; else pool = D3DPOOL_DEFAULT; HRESULT hr; DWORD usageFlags; switch (GetTextureType()) { case TT_1D: hr = device->CreateTexture( GetWidth(), 1u, GetMipmapLevelCount(), BufferUsageDX9[m_eBufferUsage], TextureFormatDX9[m_eTexFormat], pool, (IDirect3DTexture9**)&m_pTexture, 0); break; case TT_2D: usageFlags = BufferUsageDX9[m_eBufferUsage]; if (m_eBufferUsage == BU_RENDERTAGET && mipmapLevelCount == 0) { // automatic mipmap generation for RTs usageFlags |= D3DUSAGE_AUTOGENMIPMAP; m_bAutogenMipmaps = true; } hr = device->CreateTexture( GetWidth(), GetHeight(), m_bAutogenMipmaps ? 0 : GetMipmapLevelCount(), usageFlags, TextureFormatDX9[m_eTexFormat], pool, (IDirect3DTexture9**)&m_pTexture, 0); break; case TT_3D: hr = device->CreateVolumeTexture( GetWidth(), GetHeight(), GetDepth(), GetMipmapLevelCount(), BufferUsageDX9[m_eBufferUsage], TextureFormatDX9[m_eTexFormat], pool, (IDirect3DVolumeTexture9**)&m_pTexture, 0); break; case TT_CUBE: hr = device->CreateCubeTexture( GetWidth(), GetMipmapLevelCount(), BufferUsageDX9[m_eBufferUsage], TextureFormatDX9[m_eTexFormat], pool, (IDirect3DCubeTexture9**)&m_pTexture, 0); } assert(SUCCEEDED(hr)); }
bool TextureCube::Create() { Release(); if (!graphics_ || !width_ || !height_) return false; if (graphics_->IsDeviceLost()) { LOGWARNING("Texture creation while device is lost"); return true; } IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); if (!device || FAILED(device->CreateCubeTexture( width_, requestedLevels_, usage_, (D3DFORMAT)format_, (D3DPOOL)pool_, (IDirect3DCubeTexture9**)&object_, 0))) { LOGERROR("Could not create cube texture"); return false; } levels_ = ((IDirect3DCubeTexture9*)object_)->GetLevelCount(); if (usage_ & D3DUSAGE_RENDERTARGET) { for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i) { ((IDirect3DCubeTexture9*)object_)->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, (IDirect3DSurface9**)&renderSurfaces_[i]->surface_); } } return true; }
gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture) { // if the size is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) { ASSERT(mMipLevels > 0); ASSERT(mTextureWidth == mTextureHeight); IDirect3DDevice9 *device = mRenderer->getDevice(); HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(), &mTexture, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result); } } *outTexture = mTexture; return gl::Error(GL_NO_ERROR); }
bool TextureCube::Create() { Release(); if (!graphics_ || !width_ || !height_) return false; if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture creation while device is lost"); return true; } GraphicsImpl* impl = graphics_->GetImpl(); unsigned pool = usage_ > TEXTURE_STATIC ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; unsigned d3dUsage = 0; switch (usage_) { case TEXTURE_DYNAMIC: d3dUsage |= D3DUSAGE_DYNAMIC; break; case TEXTURE_RENDERTARGET: d3dUsage |= D3DUSAGE_RENDERTARGET; if (requestedLevels_ != 1) { // Check mipmap autogeneration support if (impl->CheckFormatSupport((D3DFORMAT)format_, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE)) { requestedLevels_ = 0; d3dUsage |= D3DUSAGE_AUTOGENMIPMAP; } else requestedLevels_ = 1; } break; default: break; } if (multiSample_ > 1) { // Fall back to non-multisampled if unsupported multisampling mode GraphicsImpl* impl = graphics_->GetImpl(); if (!impl->CheckMultiSampleSupport((D3DFORMAT)format_, multiSample_)) { multiSample_ = 1; autoResolve_ = false; } } IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); HRESULT hr = device->CreateCubeTexture( (UINT)width_, requestedLevels_, d3dUsage, (D3DFORMAT)format_, (D3DPOOL)pool, (IDirect3DCubeTexture9**)&object_.ptr_, nullptr); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not create cube texture", hr); URHO3D_SAFE_RELEASE(object_.ptr_); return false; } levels_ = ((IDirect3DCubeTexture9*)object_.ptr_)->GetLevelCount(); if (usage_ == TEXTURE_RENDERTARGET) { for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i) { if (multiSample_ > 1) { // Create the multisampled face rendertarget if necessary HRESULT hr = device->CreateRenderTarget( (UINT)width_, (UINT)height_, (D3DFORMAT)format_, (D3DMULTISAMPLE_TYPE)multiSample_, 0, FALSE, (IDirect3DSurface9**)&renderSurfaces_[i]->surface_, nullptr); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not create multisampled rendertarget surface", hr); URHO3D_SAFE_RELEASE(renderSurfaces_[i]->surface_); return false; } } else { hr = ((IDirect3DCubeTexture9*)object_.ptr_)->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, (IDirect3DSurface9**)&renderSurfaces_[i]->surface_); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not get rendertarget surface", hr); URHO3D_SAFE_RELEASE(renderSurfaces_[i]->surface_); return false; } } } } return true; }
void TextureDX9::Bind() { IDirect3DDevice9* device = RendererDX9::GetInstance()->GetDevice(); D3DPOOL pool; if (GetUsage() == BU_TEXTURE) pool = D3DPOOL_MANAGED; else pool = D3DPOOL_DEFAULT; HRESULT hr; DWORD usageFlags; switch (GetTextureType()) { case TT_1D: hr = device->CreateTexture( GetWidth(), 1u, GetMipmapLevelCount(), BufferUsageDX9[m_eBufferUsage], TextureFormatDX9[m_eTexFormat], pool, (IDirect3DTexture9**)&m_pTexture, 0); break; case TT_2D: usageFlags = BufferUsageDX9[m_eBufferUsage]; if (m_eBufferUsage == BU_RENDERTAGET && m_bAutogenMipmaps == true) { // automatic mipmap generation for RTs usageFlags |= D3DUSAGE_AUTOGENMIPMAP; } hr = device->CreateTexture( GetWidth(), GetHeight(), m_bAutogenMipmaps ? 0 : GetMipmapLevelCount(), usageFlags, TextureFormatDX9[m_eTexFormat], pool, (IDirect3DTexture9**)&m_pTexture, 0); break; case TT_3D: hr = device->CreateVolumeTexture( GetWidth(), GetHeight(), GetDepth(), GetMipmapLevelCount(), BufferUsageDX9[m_eBufferUsage], TextureFormatDX9[m_eTexFormat], pool, (IDirect3DVolumeTexture9**)&m_pTexture, 0); break; case TT_CUBE: hr = device->CreateCubeTexture( GetWidth(), GetMipmapLevelCount(), BufferUsageDX9[m_eBufferUsage], TextureFormatDX9[m_eTexFormat], pool, (IDirect3DCubeTexture9**)&m_pTexture, 0); } assert(SUCCEEDED(hr)); switch (GetTextureType()) { case TT_1D: case TT_2D: case TT_3D: for (unsigned int mip = 0; mip < GetMipmapLevelCount(); mip++) { if (Lock(mip, BL_WRITE_ONLY)) { Update(); Unlock(); } else if (m_eBufferUsage != BU_RENDERTAGET && m_eBufferUsage != BU_DEPTHSTENCIL) assert(false); } break; case TT_CUBE: for (unsigned int face = 0; face < 6; face++) { for (unsigned int mip = 0; mip < GetMipmapLevelCount(); mip++) { if (Lock(face, mip, BL_WRITE_ONLY)) { Update(); Unlock(); } else assert(false); } } } }