bool VertexBuffer::Create() { Release(); if (!vertexCount_ || !elementMask_) return true; if (graphics_) { if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Vertex buffer creation while device is lost"); return true; } IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); HRESULT hr = device->CreateVertexBuffer( vertexCount_ * vertexSize_, usage_, 0, (D3DPOOL)pool_, (IDirect3DVertexBuffer9**)&object_, 0); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(object_); URHO3D_LOGD3DERROR("Could not create vertex buffer", hr); return false; } } return true; }
bool IndexBuffer::Create() { Release(); if (!indexCount_) return true; if (graphics_) { if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Index buffer creation while device is lost"); return true; } IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); HRESULT hr = device->CreateIndexBuffer( indexCount_ * indexSize_, usage_, indexSize_ == sizeof(unsigned) ? D3DFMT_INDEX32 : D3DFMT_INDEX16, (D3DPOOL)pool_, (IDirect3DIndexBuffer9**)&object_, 0); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(object_) URHO3D_LOGD3DERROR("Could not create index buffer", hr); return false; } } return true; }
bool IndexBuffer::Create() { Release(); if (!indexCount_) return true; if (graphics_) { D3D11_BUFFER_DESC bufferDesc; memset(&bufferDesc, 0, sizeof bufferDesc); bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; bufferDesc.CPUAccessFlags = dynamic_ ? D3D11_CPU_ACCESS_WRITE : 0; bufferDesc.Usage = dynamic_ ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; bufferDesc.ByteWidth = (UINT)(indexCount_ * indexSize_); HRESULT hr = graphics_->GetImpl()->GetDevice()->CreateBuffer(&bufferDesc, 0, (ID3D11Buffer**)&object_); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(object_); URHO3D_LOGD3DERROR("Failed to create index buffer", hr); return false; } } return true; }
void VertexDeclaration::Create(Graphics* graphics, const PODVector<VertexDeclarationElement>& elements) { SharedArrayPtr<D3DVERTEXELEMENT9> elementArray(new D3DVERTEXELEMENT9[elements.Size() + 1]); D3DVERTEXELEMENT9* dest = elementArray; for (Vector<VertexDeclarationElement>::ConstIterator i = elements.Begin(); i != elements.End(); ++i) { dest->Stream = (WORD)i->streamIndex_; dest->Offset = (WORD)i->offset_; dest->Type = d3dElementType[i->type_]; dest->Method = D3DDECLMETHOD_DEFAULT; dest->Usage = d3dElementUsage[i->semantic_]; dest->UsageIndex = i->index_; dest++; } dest->Stream = 0xff; dest->Offset = 0; dest->Type = D3DDECLTYPE_UNUSED; dest->Method = 0; dest->Usage = 0; dest->UsageIndex = 0; IDirect3DDevice9* device = graphics->GetImpl()->GetDevice(); HRESULT hr = device->CreateVertexDeclaration(elementArray, &declaration_); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(declaration_); URHO3D_LOGD3DERROR("Failed to create vertex declaration", hr); } }
bool Texture3D::Create() { Release(); if (!graphics_ || !width_ || !height_) return false; if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture creation while device is lost"); return true; } IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); HRESULT hr = device->CreateVolumeTexture( (UINT)width_, (UINT)height_, (UINT)depth_, requestedLevels_, usage_, (D3DFORMAT)format_, (D3DPOOL)pool_, (IDirect3DVolumeTexture9**)&object_, 0); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(object_); URHO3D_LOGD3DERROR("Could not create texture", hr); return false; } levels_ = ((IDirect3DVolumeTexture9*)object_)->GetLevelCount(); return true; }
void* IndexBuffer::MapBuffer(unsigned start, unsigned count, bool discard) { void* hwData = nullptr; if (object_.ptr_) { DWORD flags = 0; if (discard && dynamic_) flags = D3DLOCK_DISCARD; HRESULT hr = ((IDirect3DIndexBuffer9*)object_.ptr_)->Lock(start * indexSize_, count * indexSize_, &hwData, flags); if (FAILED(hr)) URHO3D_LOGD3DERROR("Could not lock index buffer", hr); else lockState_ = LOCK_HARDWARE; } return hwData; }
void* VertexBuffer::MapBuffer(unsigned start, unsigned count, bool discard) { void* hwData = 0; if (object_) { DWORD flags = 0; if (discard && usage_ & D3DUSAGE_DYNAMIC) flags = D3DLOCK_DISCARD; HRESULT hr = ((IDirect3DVertexBuffer9*)object_)->Lock(start * vertexSize_, count * vertexSize_, &hwData, flags); if (FAILED(hr)) URHO3D_LOGD3DERROR("Could not lock vertex buffer", hr); else lockState_ = LOCK_HARDWARE; } return hwData; }
bool ConstantBuffer::SetSize(unsigned size) { Release(); if (!size) { URHO3D_LOGERROR("Can not create zero-sized constant buffer"); return false; } // Round up to next 16 bytes size += 15; size &= 0xfffffff0; size_ = size; dirty_ = false; shadowData_ = new unsigned char[size_]; memset(shadowData_.Get(), 0, size_); if (graphics_) { D3D11_BUFFER_DESC bufferDesc; memset(&bufferDesc, 0, sizeof bufferDesc); bufferDesc.ByteWidth = size_; bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bufferDesc.CPUAccessFlags = 0; bufferDesc.Usage = D3D11_USAGE_DEFAULT; HRESULT hr = graphics_->GetImpl()->GetDevice()->CreateBuffer(&bufferDesc, 0, (ID3D11Buffer**)&object_); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(object_); URHO3D_LOGD3DERROR("Failed to create constant buffer", hr); return false; } } return true; }
void* IndexBuffer::MapBuffer(unsigned start, unsigned count, bool discard) { void* hwData = 0; if (object_) { D3D11_MAPPED_SUBRESOURCE mappedData; mappedData.pData = 0; HRESULT hr = graphics_->GetImpl()->GetDeviceContext()->Map((ID3D11Buffer*)object_, 0, discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE, 0, &mappedData); if (FAILED(hr) || !mappedData.pData) URHO3D_LOGD3DERROR("Failed to map index buffer", hr); else { hwData = mappedData.pData; lockState_ = LOCK_HARDWARE; } } return hwData; }
bool Texture3D::Create() { Release(); if (!graphics_ || !width_ || !height_) return false; if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture creation while device is lost"); return true; } unsigned pool = usage_ > TEXTURE_STATIC ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; unsigned d3dUsage = usage_ == TEXTURE_DYNAMIC ? D3DUSAGE_DYNAMIC : 0; IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); HRESULT hr = device->CreateVolumeTexture( (UINT)width_, (UINT)height_, (UINT)depth_, requestedLevels_, d3dUsage, (D3DFORMAT)format_, (D3DPOOL)pool, (IDirect3DVolumeTexture9**)&object_, nullptr); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not create texture", hr); URHO3D_SAFE_RELEASE(object_.ptr_); return false; } levels_ = ((IDirect3DVolumeTexture9*)object_.ptr_)->GetLevelCount(); return true; }
bool IndexBuffer::Create() { Release(); if (!indexCount_) return true; if (graphics_) { if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Index buffer creation while device is lost"); return true; } unsigned pool = dynamic_ ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; unsigned d3dUsage = dynamic_ ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0; IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); HRESULT hr = device->CreateIndexBuffer( indexCount_ * indexSize_, d3dUsage, indexSize_ == sizeof(unsigned) ? D3DFMT_INDEX32 : D3DFMT_INDEX16, (D3DPOOL)pool, (IDirect3DIndexBuffer9**)&object_, nullptr); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(object_.ptr_) URHO3D_LOGD3DERROR("Could not create index buffer", hr); return false; } } return true; }
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 Texture2D::GetData(unsigned level, void* dest) const { if (!object_.ptr_) { URHO3D_LOGERROR("No texture created, can not get data"); return false; } if (!dest) { URHO3D_LOGERROR("Null destination for getting data"); return false; } if (level >= levels_) { URHO3D_LOGERROR("Illegal mip level for getting data"); return false; } if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Getting texture data while device is lost"); return false; } if (resolveDirty_) graphics_->ResolveToTexture(const_cast<Texture2D*>(this)); int levelWidth = GetLevelWidth(level); int levelHeight = GetLevelHeight(level); D3DLOCKED_RECT d3dLockedRect; RECT d3dRect; d3dRect.left = 0; d3dRect.top = 0; d3dRect.right = levelWidth; d3dRect.bottom = levelHeight; IDirect3DSurface9* offscreenSurface = nullptr; // Need to use a offscreen surface & GetRenderTargetData() for rendertargets if (renderSurface_) { if (level != 0) { URHO3D_LOGERROR("Can only get mip level 0 data from a rendertarget"); return false; } // If multisampled, must copy the surface of the resolve texture instead of the multisampled surface IDirect3DSurface9* resolveSurface = nullptr; if (multiSample_ > 1) { HRESULT hr = ((IDirect3DTexture9*)object_.ptr_)->GetSurfaceLevel(0, (IDirect3DSurface9**)&resolveSurface); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not get surface of the resolve texture", hr); URHO3D_SAFE_RELEASE(resolveSurface); return false; } } IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); HRESULT hr = device->CreateOffscreenPlainSurface((UINT)width_, (UINT)height_, (D3DFORMAT)format_, D3DPOOL_SYSTEMMEM, &offscreenSurface, nullptr); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not create surface for getting rendertarget data", hr); URHO3D_SAFE_RELEASE(offscreenSurface) URHO3D_SAFE_RELEASE(resolveSurface); return false; } if (resolveSurface) hr = device->GetRenderTargetData(resolveSurface, offscreenSurface); else hr = device->GetRenderTargetData((IDirect3DSurface9*)renderSurface_->GetSurface(), offscreenSurface); URHO3D_SAFE_RELEASE(resolveSurface); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not get rendertarget data", hr); URHO3D_SAFE_RELEASE(offscreenSurface); return false; } hr = offscreenSurface->LockRect(&d3dLockedRect, &d3dRect, D3DLOCK_READONLY); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not lock surface for getting rendertarget data", hr); URHO3D_SAFE_RELEASE(offscreenSurface); return false; } } else { HRESULT hr = ((IDirect3DTexture9*)object_.ptr_)->LockRect(level, &d3dLockedRect, &d3dRect, D3DLOCK_READONLY); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not lock texture", hr); return false; } } int height = levelHeight; if (IsCompressed()) height = (height + 3) >> 2; unsigned char* destPtr = (unsigned char*)dest; unsigned rowSize = GetRowDataSize(levelWidth); // GetRowDataSize() returns CPU-side (destination) data size, so need to convert for X8R8G8B8 if (format_ == D3DFMT_X8R8G8B8) rowSize = rowSize / 3 * 4; // Perform conversion to RGB / RGBA as necessary switch (format_) { default: for (int i = 0; i < height; ++i) { unsigned char* src = (unsigned char*)d3dLockedRect.pBits + i * d3dLockedRect.Pitch; memcpy(destPtr, src, rowSize); destPtr += rowSize; } break; case D3DFMT_X8R8G8B8: for (int i = 0; i < height; ++i) { unsigned char* src = (unsigned char*)d3dLockedRect.pBits + i * d3dLockedRect.Pitch; for (int j = 0; j < levelWidth; ++j) { destPtr[2] = *src++; destPtr[1] = *src++; destPtr[0] = *src++; ++src; destPtr += 3; } } break; case D3DFMT_A8R8G8B8: for (int i = 0; i < height; ++i) { unsigned char* src = (unsigned char*)d3dLockedRect.pBits + i * d3dLockedRect.Pitch; for (int j = 0; j < levelWidth; ++j) { destPtr[2] = *src++; destPtr[1] = *src++; destPtr[0] = *src++; destPtr[3] = *src++; destPtr += 4; } } break; } if (offscreenSurface) offscreenSurface->UnlockRect(); else ((IDirect3DTexture9*)object_.ptr_)->UnlockRect(level); URHO3D_SAFE_RELEASE(offscreenSurface); return true; }
bool Texture2D::SetData(unsigned level, int x, int y, int width, int height, const void* data) { URHO3D_PROFILE(SetTextureData); if (!object_) { URHO3D_LOGERROR("No texture created, can not set data"); return false; } if (!data) { URHO3D_LOGERROR("Null source for setting data"); return false; } if (level >= levels_) { URHO3D_LOGERROR("Illegal mip level for setting data"); return false; } int levelWidth = GetLevelWidth(level); int levelHeight = GetLevelHeight(level); if (x < 0 || x + width > levelWidth || y < 0 || y + height > levelHeight || width <= 0 || height <= 0) { URHO3D_LOGERROR("Illegal dimensions for setting data"); return false; } // If compressed, align the update region on a block if (IsCompressed()) { x &= ~3; y &= ~3; width += 3; width &= 0xfffffffc; height += 3; height &= 0xfffffffc; } unsigned char* src = (unsigned char*)data; unsigned rowSize = GetRowDataSize(width); unsigned rowStart = GetRowDataSize(x); unsigned subResource = D3D11CalcSubresource(level, 0, levels_); if (usage_ == TEXTURE_DYNAMIC) { if (IsCompressed()) { height = (height + 3) >> 2; y >>= 2; } D3D11_MAPPED_SUBRESOURCE mappedData; mappedData.pData = 0; HRESULT hr = graphics_->GetImpl()->GetDeviceContext()->Map((ID3D11Resource*)object_, subResource, D3D11_MAP_WRITE_DISCARD, 0, &mappedData); if (FAILED(hr) || !mappedData.pData) { URHO3D_LOGD3DERROR("Failed to map texture for update", hr); return false; } else { for (int row = 0; row < height; ++row) memcpy((unsigned char*)mappedData.pData + (row + y) * mappedData.RowPitch + rowStart, src + row * rowSize, rowSize); graphics_->GetImpl()->GetDeviceContext()->Unmap((ID3D11Resource*)object_, subResource); } } else {
bool Texture3D::GetData(unsigned level, void* dest) const { if (!object_) { URHO3D_LOGERROR("No texture created, can not get data"); return false; } if (!dest) { URHO3D_LOGERROR("Null destination for getting data"); return false; } if (level >= levels_) { URHO3D_LOGERROR("Illegal mip level for getting data"); return false; } if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Getting texture data while device is lost"); return false; } int levelWidth = GetLevelWidth(level); int levelHeight = GetLevelHeight(level); int levelDepth = GetLevelDepth(level); D3DLOCKED_BOX d3dLockedBox; D3DBOX d3dBox; d3dBox.Left = 0; d3dBox.Top = 0; d3dBox.Front = 0; d3dBox.Right = (UINT)levelWidth; d3dBox.Bottom = (UINT)levelHeight; d3dBox.Back = (UINT)levelDepth; HRESULT hr = ((IDirect3DVolumeTexture9*)object_)->LockBox(level, &d3dLockedBox, &d3dBox, D3DLOCK_READONLY); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not lock texture", hr); return false; } int height = levelHeight; if (IsCompressed()) height = (height + 3) >> 2; unsigned char* destPtr = (unsigned char*)dest; unsigned rowSize = GetRowDataSize(levelWidth); // GetRowDataSize() returns CPU-side (destination) data size, so need to convert for X8R8G8B8 if (format_ == D3DFMT_X8R8G8B8) rowSize = rowSize / 3 * 4; // Perform conversion to RGB / RGBA as necessary switch (format_) { default: for (int k = 0; k < levelDepth; ++k) { for (int i = 0; i < height; ++i) { unsigned char* src = (unsigned char*)d3dLockedBox.pBits + (k * d3dLockedBox.SlicePitch) + i * d3dLockedBox.RowPitch; memcpy(destPtr, src, rowSize); destPtr += rowSize; } } break; case D3DFMT_X8R8G8B8: for (int k = 0; k < levelDepth; ++k) { for (int i = 0; i < height; ++i) { unsigned char* src = (unsigned char*)d3dLockedBox.pBits + (k * d3dLockedBox.SlicePitch) + i * d3dLockedBox.RowPitch; for (int j = 0; j < levelWidth; ++j) { destPtr[2] = *src++; destPtr[1] = *src++; destPtr[0] = *src++; ++src; destPtr += 3; } } } break; case D3DFMT_A8R8G8B8: for (int k = 0; k < levelDepth; ++k) { for (int i = 0; i < height; ++i) { unsigned char* src = (unsigned char*)d3dLockedBox.pBits + (k * d3dLockedBox.SlicePitch) + i * d3dLockedBox.RowPitch; for (int j = 0; j < levelWidth; ++j) { destPtr[2] = *src++; destPtr[1] = *src++; destPtr[0] = *src++; destPtr[3] = *src++; destPtr += 4; } } } break; } ((IDirect3DVolumeTexture9*)object_)->UnlockBox(level); return true; }
bool Texture3D::SetData(unsigned level, int x, int y, int z, int width, int height, int depth, const void* data) { URHO3D_PROFILE(SetTextureData); if (!object_) { URHO3D_LOGERROR("No texture created, can not set data"); return false; } if (!data) { URHO3D_LOGERROR("Null source for setting data"); return false; } if (level >= levels_) { URHO3D_LOGERROR("Illegal mip level for setting data"); return false; } if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture data assignment while device is lost"); dataPending_ = true; return true; } if (IsCompressed()) { x &= ~3; y &= ~3; } int levelWidth = GetLevelWidth(level); int levelHeight = GetLevelHeight(level); int levelDepth = GetLevelDepth(level); if (x < 0 || x + width > levelWidth || y < 0 || y + height > levelHeight || z < 0 || z + depth > levelDepth || width <= 0 || height <= 0 || depth <= 0) { URHO3D_LOGERROR("Illegal dimensions for setting data"); return false; } D3DLOCKED_BOX d3dLockedBox; D3DBOX d3dBox; d3dBox.Left = (UINT)x; d3dBox.Top = (UINT)y; d3dBox.Front = (UINT)z; d3dBox.Right = (UINT)(x + width); d3dBox.Bottom = (UINT)(y + height); d3dBox.Back = (UINT)(z + depth); DWORD flags = 0; if (level == 0 && x == 0 && y == 0 && z == 0 && width == levelWidth && height == levelHeight && depth == levelDepth && pool_ == D3DPOOL_DEFAULT) flags |= D3DLOCK_DISCARD; HRESULT hr = ((IDirect3DVolumeTexture9*)object_)->LockBox(level, &d3dLockedBox, (flags & D3DLOCK_DISCARD) ? 0 : &d3dBox, flags); if (FAILED(hr)) { URHO3D_LOGD3DERROR("Could not lock texture", hr); return false; } if (IsCompressed()) { height = (height + 3) >> 2; y >>= 2; } unsigned char* src = (unsigned char*)data; unsigned rowSize = GetRowDataSize(width); // GetRowDataSize() returns CPU-side (source) data size, so need to convert for X8R8G8B8 if (format_ == D3DFMT_X8R8G8B8) rowSize = rowSize / 3 * 4; // Perform conversion from RGB / RGBA as necessary switch (format_) { default: for (int k = 0; k < levelDepth; ++k) { for (int i = 0; i < height; ++i) { unsigned char * dest = (unsigned char*)d3dLockedBox.pBits + (k * d3dLockedBox.SlicePitch) + i * d3dLockedBox.RowPitch; memcpy(dest, src, rowSize); src += rowSize; } } break; case D3DFMT_X8R8G8B8: for (int k = 0; k < levelDepth; ++k) { for (int i = 0; i < height; ++i) { unsigned char * dest = (unsigned char*)d3dLockedBox.pBits + (k * d3dLockedBox.SlicePitch) + i * d3dLockedBox.RowPitch; for (int j = 0; j < width; ++j) { *dest++ = src[2]; *dest++ = src[1]; *dest++ = src[0]; *dest++ = 255; src += 3; } } } break; case D3DFMT_A8R8G8B8: for (int k = 0; k < levelDepth; ++k) { for (int i = 0; i < height; ++i) { unsigned char * dest = (unsigned char*)d3dLockedBox.pBits + (k * d3dLockedBox.SlicePitch) + i * d3dLockedBox.RowPitch; for (int j = 0; j < width; ++j) { *dest++ = src[2]; *dest++ = src[1]; *dest++ = src[0]; *dest++ = src[3]; src += 4; } } } break; } ((IDirect3DVolumeTexture9*)object_)->UnlockBox(level); 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; }
bool Texture2D::Create() { Release(); if (!graphics_ || !width_ || !height_) return false; if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture creation while device is lost"); return true; } IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice(); // If creating a depth-stencil texture, and it is not supported, create a depth-stencil surface instead if (usage_ & D3DUSAGE_DEPTHSTENCIL && !graphics_->GetImpl()->CheckFormatSupport((D3DFORMAT)format_, usage_, D3DRTYPE_TEXTURE)) { HRESULT hr = device->CreateDepthStencilSurface( (UINT)width_, (UINT)height_, (D3DFORMAT)format_, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9**)&renderSurface_->surface_, 0); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(renderSurface_->surface_); URHO3D_LOGD3DERROR("Could not create depth-stencil surface", hr); return false; } levels_ = 1; } else { HRESULT hr = graphics_->GetImpl()->GetDevice()->CreateTexture( (UINT)width_, (UINT)height_, requestedLevels_, usage_, (D3DFORMAT)format_, (D3DPOOL)pool_, (IDirect3DTexture9**)&object_, 0); if (FAILED(hr)) { URHO3D_SAFE_RELEASE(object_); URHO3D_LOGD3DERROR("Could not create texture", hr); return false; } levels_ = ((IDirect3DTexture9*)object_)->GetLevelCount(); if (usage_ & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) { hr = ((IDirect3DTexture9*)object_)->GetSurfaceLevel(0, (IDirect3DSurface9**)&renderSurface_->surface_); if (FAILED(hr)) URHO3D_LOGD3DERROR("Could not get rendertarget surface", hr); } } return true; }