bool Texture2D::Create() { Release(); if (!graphics_ || !width_ || !height_) return false; if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture creation while device is lost"); return true; } if (multiSample_ > 1 && !autoResolve_) { URHO3D_LOGWARNING("Multisampled texture without autoresolve is not supported on Direct3D9"); autoResolve_ = 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; case TEXTURE_DEPTHSTENCIL: d3dUsage |= D3DUSAGE_DEPTHSTENCIL; // No mipmaps for depth-stencil textures requestedLevels_ = 1; break; default: break; } if (multiSample_ > 1) { // Fall back to non-multisampled if unsupported multisampling mode if (!impl->CheckMultiSampleSupport((D3DFORMAT)format_, multiSample_)) { multiSample_ = 1; autoResolve_ = false; } } IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); // If creating a depth-stencil texture, and it is not supported, create a depth-stencil surface instead // Multisampled surfaces need also to be created this way if (usage_ == TEXTURE_DEPTHSTENCIL && (multiSample_ > 1 || !graphics_->GetImpl()->CheckFormatSupport((D3DFORMAT)format_, d3dUsage, D3DRTYPE_TEXTURE))) { HRESULT hr = device->CreateDepthStencilSurface( (UINT)width_, (UINT)height_, (D3DFORMAT)format_, (multiSample_ > 1) ? (D3DMULTISAMPLE_TYPE)multiSample_ : D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9**)&renderSurface_->surface_, nullptr); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not create depth-stencil surface", hr); URHO3D_SAFE_RELEASE(renderSurface_->surface_); return false; } levels_ = 1; } else { HRESULT hr = graphics_->GetImpl()->GetDevice()->CreateTexture( (UINT)width_, (UINT)height_, requestedLevels_, d3dUsage, (D3DFORMAT)format_, (D3DPOOL)pool, (IDirect3DTexture9**)&object_, nullptr); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not create texture", hr); URHO3D_SAFE_RELEASE(object_.ptr_); return false; } levels_ = ((IDirect3DTexture9*)object_.ptr_)->GetLevelCount(); // Create the multisampled rendertarget for rendering to if necessary if (usage_ == TEXTURE_RENDERTARGET && multiSample_ > 1) { HRESULT hr = device->CreateRenderTarget( (UINT)width_, (UINT)height_, (D3DFORMAT)format_, (D3DMULTISAMPLE_TYPE)multiSample_, 0, FALSE, (IDirect3DSurface9**)&renderSurface_->surface_, nullptr); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not create multisampled rendertarget surface", hr); URHO3D_SAFE_RELEASE(renderSurface_->surface_); return false; } } else if (usage_ >= TEXTURE_RENDERTARGET) { // Else use the texture surface directly for rendering hr = ((IDirect3DTexture9*)object_.ptr_)->GetSurfaceLevel(0, (IDirect3DSurface9**)&renderSurface_->surface_); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not get rendertarget surface", hr); URHO3D_SAFE_RELEASE(renderSurface_->surface_); return false; } } } return true; }
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; }