bool TextureCube::Load(CubeMapFace face, SharedPtr<Image> image, bool useAlpha) { if (!image) { LOGERROR("Null image, can not load texture"); return false; } unsigned memoryUse = 0; int quality = QUALITY_HIGH; Renderer* renderer = GetSubsystem<Renderer>(); if (renderer) quality = renderer->GetTextureQuality(); if (!image->IsCompressed()) { unsigned char* levelData = image->GetData(); int levelWidth = image->GetWidth(); int levelHeight = image->GetHeight(); unsigned components = image->GetComponents(); unsigned format = 0; if (levelWidth != levelHeight) { LOGERROR("Cube texture width not equal to height"); return false; } // Discard unnecessary mip levels for (unsigned i = 0; i < mipsToSkip_[quality]; ++i) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } switch (components) { case 1: format = useAlpha ? Graphics::GetAlphaFormat() : Graphics::GetLuminanceFormat(); break; case 2: format = Graphics::GetLuminanceAlphaFormat(); break; case 3: format = Graphics::GetRGBFormat(); break; case 4: format = Graphics::GetRGBAFormat(); break; } // Create the texture when face 0 is being loaded, check that rest of the faces are same size & format if (!face) { // If image was previously compressed, reset number of requested levels to avoid error if level count is too high for new size if (IsCompressed() && requestedLevels_ > 1) requestedLevels_ = 0; SetSize(levelWidth, format); } else { if (!object_) { LOGERROR("Cube texture face 0 must be loaded first"); return false; } if (levelWidth != width_ || format != format_) { LOGERROR("Cube texture face does not match size or format of face 0"); return false; } } for (unsigned i = 0; i < levels_; ++i) { SetData(face, i, 0, 0, levelWidth, levelHeight, levelData); memoryUse += levelWidth * levelHeight * components; if (i < levels_ - 1) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } } } else { int width = image->GetWidth(); int height = image->GetHeight(); unsigned levels = image->GetNumCompressedLevels(); unsigned format = graphics_->GetFormat(image->GetCompressedFormat()); bool needDecompress = false; if (width != height) { LOGERROR("Cube texture width not equal to height"); return false; } if (!format) { format = Graphics::GetRGBAFormat(); needDecompress = true; } unsigned mipsToSkip = mipsToSkip_[quality]; if (mipsToSkip >= levels) mipsToSkip = levels - 1; while (mipsToSkip && (width / (1 << mipsToSkip) < 4 || height / (1 << mipsToSkip) < 4)) --mipsToSkip; width /= (1 << mipsToSkip); height /= (1 << mipsToSkip); // Create the texture when face 0 is being loaded, assume rest of the faces are same size & format if (!face) { SetNumLevels(Max((int)(levels - mipsToSkip), 1)); SetSize(width, format); } else { if (!object_) { LOGERROR("Cube texture face 0 must be loaded first"); return false; } if (width != width_ || format != format_) { LOGERROR("Cube texture face does not match size or format of face 0"); return false; } } for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i) { CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip); if (!needDecompress) { SetData(face, i, 0, 0, level.width_, level.height_, level.data_); memoryUse += level.rows_ * level.rowSize_; } else { unsigned char* rgbaData = new unsigned char[level.width_ * level.height_ * 4]; level.Decompress(rgbaData); SetData(face, i, 0, 0, level.width_, level.height_, rgbaData); memoryUse += level.width_ * level.height_ * 4; delete[] rgbaData; } } } faceMemoryUse_[face] = memoryUse; unsigned totalMemoryUse = sizeof(TextureCube); for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i) totalMemoryUse += faceMemoryUse_[i]; SetMemoryUse(totalMemoryUse); return true; }
bool Texture2D::SetData(SharedPtr<Image> image, bool useAlpha) { if (!image) { URHO3D_LOGERROR("Null image, can not set data"); return false; } unsigned memoryUse = sizeof(Texture2D); int quality = QUALITY_HIGH; Renderer* renderer = GetSubsystem<Renderer>(); if (renderer) quality = renderer->GetTextureQuality(); if (!image->IsCompressed()) { // Convert unsuitable formats to RGBA unsigned components = image->GetComponents(); if (Graphics::GetGL3Support() && ((components == 1 && !useAlpha) || components == 2)) { image = image->ConvertToRGBA(); if (!image) return false; components = image->GetComponents(); } unsigned char* levelData = image->GetData(); int levelWidth = image->GetWidth(); int levelHeight = image->GetHeight(); unsigned format = 0; // Discard unnecessary mip levels for (unsigned i = 0; i < mipsToSkip_[quality]; ++i) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } switch (components) { case 1: format = useAlpha ? Graphics::GetAlphaFormat() : Graphics::GetLuminanceFormat(); break; case 2: format = Graphics::GetLuminanceAlphaFormat(); break; case 3: format = Graphics::GetRGBFormat(); break; case 4: format = Graphics::GetRGBAFormat(); break; default: assert(false); // Should not reach here break; } // If image was previously compressed, reset number of requested levels to avoid error if level count is too high for new size if (IsCompressed() && requestedLevels_ > 1) requestedLevels_ = 0; SetSize(levelWidth, levelHeight, format); if (!object_) return false; for (unsigned i = 0; i < levels_; ++i) { SetData(i, 0, 0, levelWidth, levelHeight, levelData); memoryUse += levelWidth * levelHeight * components; if (i < levels_ - 1) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } } } else { int width = image->GetWidth(); int height = image->GetHeight(); unsigned levels = image->GetNumCompressedLevels(); unsigned format = graphics_->GetFormat(image->GetCompressedFormat()); bool needDecompress = false; if (!format) { format = Graphics::GetRGBAFormat(); needDecompress = true; } unsigned mipsToSkip = mipsToSkip_[quality]; if (mipsToSkip >= levels) mipsToSkip = levels - 1; while (mipsToSkip && (width / (1 << mipsToSkip) < 4 || height / (1 << mipsToSkip) < 4)) --mipsToSkip; width /= (1 << mipsToSkip); height /= (1 << mipsToSkip); SetNumLevels((unsigned)Max((int)(levels - mipsToSkip), 1)); SetSize(width, height, format); for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i) { CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip); if (!needDecompress) { SetData(i, 0, 0, level.width_, level.height_, level.data_); memoryUse += level.rows_ * level.rowSize_; } else { unsigned char* rgbaData = new unsigned char[level.width_ * level.height_ * 4]; level.Decompress(rgbaData); SetData(i, 0, 0, level.width_, level.height_, rgbaData); memoryUse += level.width_ * level.height_ * 4; delete[] rgbaData; } } } SetMemoryUse(memoryUse); return true; }
bool Texture2D::Load(SharedPtr<Image> image, bool useAlpha) { if (!image) { LOGERROR("Null image, can not load texture"); return false; } unsigned memoryUse = sizeof(Texture2D); int quality = QUALITY_HIGH; Renderer* renderer = GetSubsystem<Renderer>(); if (renderer) quality = renderer->GetTextureQuality(); if (!image->IsCompressed()) { unsigned char* levelData = image->GetData(); int levelWidth = image->GetWidth(); int levelHeight = image->GetHeight(); unsigned components = image->GetComponents(); unsigned format = 0; // Discard unnecessary mip levels for (unsigned i = 0; i < mipsToSkip_[quality]; ++i) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } switch (components) { case 1: format = useAlpha ? Graphics::GetAlphaFormat() : Graphics::GetLuminanceFormat(); break; case 2: format = Graphics::GetLuminanceAlphaFormat(); break; case 3: format = Graphics::GetRGBFormat(); break; case 4: format = Graphics::GetRGBAFormat(); break; } SetSize(levelWidth, levelHeight, format); if (!object_) return false; for (unsigned i = 0; i < levels_; ++i) { SetData(i, 0, 0, levelWidth, levelHeight, levelData); memoryUse += levelWidth * levelHeight * components; if (i < levels_ - 1) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } } } else { int width = image->GetWidth(); int height = image->GetHeight(); unsigned levels = image->GetNumCompressedLevels(); unsigned format = graphics_->GetFormat(image->GetCompressedFormat()); bool needDecompress = false; if (!format) { format = Graphics::GetRGBAFormat(); needDecompress = true; } unsigned mipsToSkip = mipsToSkip_[quality]; if (mipsToSkip >= levels) mipsToSkip = levels - 1; while (mipsToSkip && (width / (1 << mipsToSkip) < 4 || height / (1 << mipsToSkip) < 4)) --mipsToSkip; width /= (1 << mipsToSkip); height /= (1 << mipsToSkip); SetNumLevels(Max((int)(levels - mipsToSkip), 1)); SetSize(width, height, format); for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i) { CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip); if (!needDecompress) { SetData(i, 0, 0, level.width_, level.height_, level.data_); memoryUse += level.rows_ * level.rowSize_; } else { unsigned char* rgbaData = new unsigned char[level.width_ * level.height_ * 4]; level.Decompress(rgbaData); SetData(i, 0, 0, level.width_, level.height_, rgbaData); memoryUse += level.width_ * level.height_ * 4; delete[] rgbaData; } } } SetMemoryUse(memoryUse); return true; }
bool Texture2DArray::SetData(unsigned layer, Image* image, bool useAlpha) { if (!image) { URHO3D_LOGERROR("Null image, can not set data"); return false; } if (!layers_) { URHO3D_LOGERROR("Number of layers in the array must be set first"); return false; } if (layer >= layers_) { URHO3D_LOGERROR("Illegal layer for setting data"); return false; } // Use a shared ptr for managing the temporary mip images created during this function SharedPtr<Image> mipImage; unsigned memoryUse = 0; int quality = QUALITY_HIGH; Renderer* renderer = GetSubsystem<Renderer>(); if (renderer) quality = renderer->GetTextureQuality(); if (!image->IsCompressed()) { unsigned char* levelData = image->GetData(); int levelWidth = image->GetWidth(); int levelHeight = image->GetHeight(); unsigned components = image->GetComponents(); unsigned format = 0; // Discard unnecessary mip levels for (unsigned i = 0; i < mipsToSkip_[quality]; ++i) { mipImage = image->GetNextLevel(); image = mipImage; levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } switch (components) { case 1: format = Graphics::GetAlphaFormat(); break; case 4: format = Graphics::GetRGBAFormat(); break; default: break; } // Create the texture array when layer 0 is being loaded, check that rest of the layers are same size & format if (!layer) { // If image was previously compressed, reset number of requested levels to avoid error if level count is too high for new size if (IsCompressed() && requestedLevels_ > 1) requestedLevels_ = 0; // Create the texture array (the number of layers must have been already set) SetSize(0, levelWidth, levelHeight, format); } else { if (!object_.ptr_) { // Do not spam this error on D3D9 //URHO3D_LOGERROR("Texture array layer 0 must be loaded first"); return false; } if (levelWidth != width_ || levelHeight != height_ || format != format_) { URHO3D_LOGERROR("Texture array layer does not match size or format of layer 0"); return false; } } for (unsigned i = 0; i < levels_; ++i) { SetData(layer, i, 0, 0, levelWidth, levelHeight, levelData); memoryUse += levelWidth * levelHeight * components; if (i < levels_ - 1) { mipImage = image->GetNextLevel(); image = mipImage; levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } } } else { int width = image->GetWidth(); int height = image->GetHeight(); unsigned levels = image->GetNumCompressedLevels(); unsigned format = graphics_->GetFormat(image->GetCompressedFormat()); bool needDecompress = false; if (!format) { format = Graphics::GetRGBAFormat(); needDecompress = true; } unsigned mipsToSkip = mipsToSkip_[quality]; if (mipsToSkip >= levels) mipsToSkip = levels - 1; while (mipsToSkip && (width / (1 << mipsToSkip) < 4 || height / (1 << mipsToSkip) < 4)) --mipsToSkip; width /= (1 << mipsToSkip); height /= (1 << mipsToSkip); // Create the texture array when layer 0 is being loaded, assume rest of the layers are same size & format if (!layer) { SetNumLevels(Max((levels - mipsToSkip), 1U)); SetSize(0, width, height, format); } else { if (!object_.ptr_) { //URHO3D_LOGERROR("Texture array layer 0 must be loaded first"); return false; } if (width != width_ || height != height_ || format != format_) { URHO3D_LOGERROR("Texture array layer does not match size or format of layer 0"); return false; } } for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i) { CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip); if (!needDecompress) { SetData(layer, i, 0, 0, level.width_, level.height_, level.data_); memoryUse += level.rows_ * level.rowSize_; } else { unsigned char* rgbaData = new unsigned char[level.width_ * level.height_ * 4]; level.Decompress(rgbaData); SetData(layer, i, 0, 0, level.width_, level.height_, rgbaData); memoryUse += level.width_ * level.height_ * 4; delete[] rgbaData; } } } layerMemoryUse_[layer] = memoryUse; unsigned totalMemoryUse = sizeof(Texture2DArray) + layerMemoryUse_.Capacity() * sizeof(unsigned); for (unsigned i = 0; i < layers_; ++i) totalMemoryUse += layerMemoryUse_[i]; SetMemoryUse(totalMemoryUse); return true; }
bool TextureCube::SetData(CubeMapFace face, Image* image, bool useAlpha) { if (!image) { URHO3D_LOGERROR("Null image, can not set face data"); return false; } // Use a shared ptr for managing the temporary mip images created during this function SharedPtr<Image> mipImage; unsigned memoryUse = 0; int quality = QUALITY_HIGH; auto* renderer = GetSubsystem<Renderer>(); if (renderer) quality = renderer->GetTextureQuality(); if (!image->IsCompressed()) { // Convert unsuitable formats to RGBA unsigned components = image->GetComponents(); if (Graphics::GetGL3Support() && ((components == 1 && !useAlpha) || components == 2)) { mipImage = image->ConvertToRGBA(); image = mipImage; if (!image) return false; components = image->GetComponents(); } unsigned char* levelData = image->GetData(); int levelWidth = image->GetWidth(); int levelHeight = image->GetHeight(); unsigned format = 0; if (levelWidth != levelHeight) { URHO3D_LOGERROR("Cube texture width not equal to height"); return false; } // Discard unnecessary mip levels for (unsigned i = 0; i < mipsToSkip_[quality]; ++i) { mipImage = image->GetNextLevel(); image = mipImage; levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } switch (components) { case 1: format = useAlpha ? Graphics::GetAlphaFormat() : Graphics::GetLuminanceFormat(); break; case 2: format = Graphics::GetLuminanceAlphaFormat(); break; case 3: format = Graphics::GetRGBFormat(); break; case 4: format = Graphics::GetRGBAFormat(); break; default: assert(false); // Should not reach here break; } // Create the texture when face 0 is being loaded, check that rest of the faces are same size & format if (!face) { // If image was previously compressed, reset number of requested levels to avoid error if level count is too high for new size if (IsCompressed() && requestedLevels_ > 1) requestedLevels_ = 0; SetSize(levelWidth, format); } else { if (!object_.name_) { URHO3D_LOGERROR("Cube texture face 0 must be loaded first"); return false; } if (levelWidth != width_ || format != format_) { URHO3D_LOGERROR("Cube texture face does not match size or format of face 0"); return false; } } for (unsigned i = 0; i < levels_; ++i) { SetData(face, i, 0, 0, levelWidth, levelHeight, levelData); memoryUse += levelWidth * levelHeight * components; if (i < levels_ - 1) { mipImage = image->GetNextLevel(); image = mipImage; levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } } } else { int width = image->GetWidth(); int height = image->GetHeight(); unsigned levels = image->GetNumCompressedLevels(); unsigned format = graphics_->GetFormat(image->GetCompressedFormat()); bool needDecompress = false; if (width != height) { URHO3D_LOGERROR("Cube texture width not equal to height"); return false; } if (!format) { format = Graphics::GetRGBAFormat(); needDecompress = true; } unsigned mipsToSkip = mipsToSkip_[quality]; if (mipsToSkip >= levels) mipsToSkip = levels - 1; while (mipsToSkip && (width / (1u << mipsToSkip) < 4 || height / (1u << mipsToSkip) < 4)) --mipsToSkip; width /= (1u << mipsToSkip); height /= (1u << mipsToSkip); // Create the texture when face 0 is being loaded, assume rest of the faces are same size & format if (!face) { SetNumLevels(Max((levels - mipsToSkip), 1U)); SetSize(width, format); } else { if (!object_.name_) { URHO3D_LOGERROR("Cube texture face 0 must be loaded first"); return false; } if (width != width_ || format != format_) { URHO3D_LOGERROR("Cube texture face does not match size or format of face 0"); return false; } } for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i) { CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip); if (!needDecompress) { SetData(face, i, 0, 0, level.width_, level.height_, level.data_); memoryUse += level.rows_ * level.rowSize_; } else { auto* rgbaData = new unsigned char[level.width_ * level.height_ * 4]; level.Decompress(rgbaData); SetData(face, i, 0, 0, level.width_, level.height_, rgbaData); memoryUse += level.width_ * level.height_ * 4; delete[] rgbaData; } } } faceMemoryUse_[face] = memoryUse; unsigned totalMemoryUse = sizeof(TextureCube); for (unsigned memoryUse : faceMemoryUse_) totalMemoryUse += memoryUse; SetMemoryUse(totalMemoryUse); return true; }