|
@@ -36,25 +36,6 @@
|
|
|
namespace Urho3D
|
|
namespace Urho3D
|
|
|
{
|
|
{
|
|
|
|
|
|
|
|
-static const char* addressModeNames[] =
|
|
|
|
|
-{
|
|
|
|
|
- "wrap",
|
|
|
|
|
- "mirror",
|
|
|
|
|
- "clamp",
|
|
|
|
|
- "border",
|
|
|
|
|
- 0
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-static const char* filterModeNames[] =
|
|
|
|
|
-{
|
|
|
|
|
- "nearest",
|
|
|
|
|
- "bilinear",
|
|
|
|
|
- "trilinear",
|
|
|
|
|
- "anisotropic",
|
|
|
|
|
- "default",
|
|
|
|
|
- 0
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
static const D3D11_FILTER d3dFilterMode[] =
|
|
static const D3D11_FILTER d3dFilterMode[] =
|
|
|
{
|
|
{
|
|
|
D3D11_FILTER_MIN_MAG_MIP_POINT,
|
|
D3D11_FILTER_MIN_MAG_MIP_POINT,
|
|
@@ -75,136 +56,28 @@ static const D3D11_TEXTURE_ADDRESS_MODE d3dAddressMode[] =
|
|
|
D3D11_TEXTURE_ADDRESS_BORDER
|
|
D3D11_TEXTURE_ADDRESS_BORDER
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-Texture::Texture(Context* context) :
|
|
|
|
|
- Resource(context),
|
|
|
|
|
- GPUObject(GetSubsystem<Graphics>()),
|
|
|
|
|
- shaderResourceView_(0),
|
|
|
|
|
- sampler_(0),
|
|
|
|
|
- format_(DXGI_FORMAT_UNKNOWN),
|
|
|
|
|
- usage_(TEXTURE_STATIC),
|
|
|
|
|
- levels_(0),
|
|
|
|
|
- requestedLevels_(0),
|
|
|
|
|
- width_(0),
|
|
|
|
|
- height_(0),
|
|
|
|
|
- depth_(0),
|
|
|
|
|
- shadowCompare_(false),
|
|
|
|
|
- filterMode_(FILTER_DEFAULT),
|
|
|
|
|
- sRGB_(false),
|
|
|
|
|
- parametersDirty_(true)
|
|
|
|
|
-{
|
|
|
|
|
- for (int i = 0; i < MAX_COORDS; ++i)
|
|
|
|
|
- addressMode_[i] = ADDRESS_WRAP;
|
|
|
|
|
- for (int i = 0; i < MAX_TEXTURE_QUALITY_LEVELS; ++i)
|
|
|
|
|
- mipsToSkip_[i] = (unsigned)(MAX_TEXTURE_QUALITY_LEVELS - 1 - i);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-Texture::~Texture()
|
|
|
|
|
-{
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetNumLevels(unsigned levels)
|
|
|
|
|
-{
|
|
|
|
|
- if (usage_ > TEXTURE_RENDERTARGET)
|
|
|
|
|
- requestedLevels_ = 1;
|
|
|
|
|
- else
|
|
|
|
|
- requestedLevels_ = levels;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetFilterMode(TextureFilterMode mode)
|
|
|
|
|
-{
|
|
|
|
|
- filterMode_ = mode;
|
|
|
|
|
- parametersDirty_ = true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetAddressMode(TextureCoordinate coord, TextureAddressMode mode)
|
|
|
|
|
-{
|
|
|
|
|
- addressMode_[coord] = mode;
|
|
|
|
|
- parametersDirty_ = true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetShadowCompare(bool enable)
|
|
|
|
|
-{
|
|
|
|
|
- shadowCompare_ = enable;
|
|
|
|
|
- parametersDirty_ = true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetBorderColor(const Color& color)
|
|
|
|
|
-{
|
|
|
|
|
- borderColor_ = color;
|
|
|
|
|
- parametersDirty_ = true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
void Texture::SetSRGB(bool enable)
|
|
void Texture::SetSRGB(bool enable)
|
|
|
{
|
|
{
|
|
|
if (graphics_)
|
|
if (graphics_)
|
|
|
enable &= graphics_->GetSRGBSupport();
|
|
enable &= graphics_->GetSRGBSupport();
|
|
|
|
|
|
|
|
- // Note: on D3D11 sRGB only affects the texture before creation
|
|
|
|
|
- sRGB_ = enable;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetBackupTexture(Texture* texture)
|
|
|
|
|
-{
|
|
|
|
|
- backupTexture_ = texture;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetMipsToSkip(int quality, int toSkip)
|
|
|
|
|
-{
|
|
|
|
|
- if (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS)
|
|
|
|
|
|
|
+ if (enable != sRGB_)
|
|
|
{
|
|
{
|
|
|
- mipsToSkip_[quality] = (unsigned)toSkip;
|
|
|
|
|
-
|
|
|
|
|
- // Make sure a higher quality level does not actually skip more mips
|
|
|
|
|
- for (int i = 1; i < MAX_TEXTURE_QUALITY_LEVELS; ++i)
|
|
|
|
|
- {
|
|
|
|
|
- if (mipsToSkip_[i] > mipsToSkip_[i - 1])
|
|
|
|
|
- mipsToSkip_[i] = mipsToSkip_[i - 1];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ sRGB_ = enable;
|
|
|
|
|
+ // If texture had already been created, must recreate it to set the sRGB texture format
|
|
|
|
|
+ if (object_.name_)
|
|
|
|
|
+ Create();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool Texture::IsCompressed() const
|
|
|
|
|
-{
|
|
|
|
|
- return format_ == DXGI_FORMAT_BC1_UNORM || format_ == DXGI_FORMAT_BC2_UNORM || format_ == DXGI_FORMAT_BC3_UNORM;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int Texture::GetMipsToSkip(int quality) const
|
|
|
|
|
-{
|
|
|
|
|
- return (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS) ? mipsToSkip_[quality] : 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int Texture::GetLevelWidth(unsigned level) const
|
|
|
|
|
|
|
+bool Texture::GetParametersDirty() const
|
|
|
{
|
|
{
|
|
|
- if (level > levels_)
|
|
|
|
|
- return 0;
|
|
|
|
|
- return Max(width_ >> level, 1);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int Texture::GetLevelHeight(unsigned level) const
|
|
|
|
|
-{
|
|
|
|
|
- if (level > levels_)
|
|
|
|
|
- return 0;
|
|
|
|
|
- return Max(height_ >> level, 1);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-int Texture::GetLevelDepth(unsigned level) const
|
|
|
|
|
-{
|
|
|
|
|
- if (level > levels_)
|
|
|
|
|
- return 0;
|
|
|
|
|
- return Max(depth_ >> level, 1);
|
|
|
|
|
|
|
+ return parametersDirty_ || !sampler_;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-unsigned Texture::GetDataSize(int width, int height) const
|
|
|
|
|
-{
|
|
|
|
|
- if (IsCompressed())
|
|
|
|
|
- return GetRowDataSize(width) * ((height + 3) >> 2);
|
|
|
|
|
- else
|
|
|
|
|
- return GetRowDataSize(width) * height;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-unsigned Texture::GetDataSize(int width, int height, int depth) const
|
|
|
|
|
|
|
+bool Texture::IsCompressed() const
|
|
|
{
|
|
{
|
|
|
- return depth * GetDataSize(width, height);
|
|
|
|
|
|
|
+ return format_ == DXGI_FORMAT_BC1_UNORM || format_ == DXGI_FORMAT_BC2_UNORM || format_ == DXGI_FORMAT_BC3_UNORM;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
unsigned Texture::GetRowDataSize(int width) const
|
|
unsigned Texture::GetRowDataSize(int width) const
|
|
@@ -248,77 +121,6 @@ unsigned Texture::GetRowDataSize(int width) const
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-unsigned Texture::GetComponents() const
|
|
|
|
|
-{
|
|
|
|
|
- if (!width_ || IsCompressed())
|
|
|
|
|
- return 0;
|
|
|
|
|
- else
|
|
|
|
|
- return GetRowDataSize(width_) / width_;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetParameters(XMLFile* file)
|
|
|
|
|
-{
|
|
|
|
|
- if (!file)
|
|
|
|
|
- return;
|
|
|
|
|
-
|
|
|
|
|
- XMLElement rootElem = file->GetRoot();
|
|
|
|
|
- SetParameters(rootElem);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetParameters(const XMLElement& element)
|
|
|
|
|
-{
|
|
|
|
|
- XMLElement paramElem = element.GetChild();
|
|
|
|
|
- while (paramElem)
|
|
|
|
|
- {
|
|
|
|
|
- String name = paramElem.GetName();
|
|
|
|
|
-
|
|
|
|
|
- if (name == "address")
|
|
|
|
|
- {
|
|
|
|
|
- String coord = paramElem.GetAttributeLower("coord");
|
|
|
|
|
- if (coord.Length() >= 1)
|
|
|
|
|
- {
|
|
|
|
|
- TextureCoordinate coordIndex = (TextureCoordinate)(coord[0] - 'u');
|
|
|
|
|
- String mode = paramElem.GetAttributeLower("mode");
|
|
|
|
|
- SetAddressMode(coordIndex, (TextureAddressMode)GetStringListIndex(mode.CString(), addressModeNames, ADDRESS_WRAP));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (name == "border")
|
|
|
|
|
- SetBorderColor(paramElem.GetColor("color"));
|
|
|
|
|
-
|
|
|
|
|
- if (name == "filter")
|
|
|
|
|
- {
|
|
|
|
|
- String mode = paramElem.GetAttributeLower("mode");
|
|
|
|
|
- SetFilterMode((TextureFilterMode)GetStringListIndex(mode.CString(), filterModeNames, FILTER_DEFAULT));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (name == "mipmap")
|
|
|
|
|
- SetNumLevels(paramElem.GetBool("enable") ? 0 : 1);
|
|
|
|
|
-
|
|
|
|
|
- if (name == "quality")
|
|
|
|
|
- {
|
|
|
|
|
- if (paramElem.HasAttribute("low"))
|
|
|
|
|
- SetMipsToSkip(QUALITY_LOW, paramElem.GetInt("low"));
|
|
|
|
|
- if (paramElem.HasAttribute("med"))
|
|
|
|
|
- SetMipsToSkip(QUALITY_MEDIUM, paramElem.GetInt("med"));
|
|
|
|
|
- if (paramElem.HasAttribute("medium"))
|
|
|
|
|
- SetMipsToSkip(QUALITY_MEDIUM, paramElem.GetInt("medium"));
|
|
|
|
|
- if (paramElem.HasAttribute("high"))
|
|
|
|
|
- SetMipsToSkip(QUALITY_HIGH, paramElem.GetInt("high"));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (name == "srgb")
|
|
|
|
|
- SetSRGB(paramElem.GetBool("enable"));
|
|
|
|
|
-
|
|
|
|
|
- paramElem = paramElem.GetNext();
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void Texture::SetParametersDirty()
|
|
|
|
|
-{
|
|
|
|
|
- parametersDirty_ = true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
void Texture::UpdateParameters()
|
|
void Texture::UpdateParameters()
|
|
|
{
|
|
{
|
|
|
if ((!parametersDirty_ && sampler_) || !object_.ptr_)
|
|
if ((!parametersDirty_ && sampler_) || !object_.ptr_)
|
|
@@ -352,40 +154,6 @@ void Texture::UpdateParameters()
|
|
|
parametersDirty_ = false;
|
|
parametersDirty_ = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-unsigned Texture::CheckMaxLevels(int width, int height, unsigned requestedLevels)
|
|
|
|
|
-{
|
|
|
|
|
- unsigned maxLevels = 1;
|
|
|
|
|
- while (width > 1 && height > 1)
|
|
|
|
|
- {
|
|
|
|
|
- ++maxLevels;
|
|
|
|
|
- width >>= 1;
|
|
|
|
|
- height >>= 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!requestedLevels || maxLevels < requestedLevels)
|
|
|
|
|
- return maxLevels;
|
|
|
|
|
- else
|
|
|
|
|
- return requestedLevels;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-unsigned Texture::CheckMaxLevels(int width, int height, int depth, unsigned requestedLevels)
|
|
|
|
|
-{
|
|
|
|
|
- unsigned maxLevels = 1;
|
|
|
|
|
- while (width > 1 && height > 1 && depth > 1)
|
|
|
|
|
- {
|
|
|
|
|
- ++maxLevels;
|
|
|
|
|
- width >>= 1;
|
|
|
|
|
- height >>= 1;
|
|
|
|
|
- depth >>= 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!requestedLevels || maxLevels < requestedLevels)
|
|
|
|
|
- return maxLevels;
|
|
|
|
|
- else
|
|
|
|
|
- return requestedLevels;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
unsigned Texture::GetSRVFormat(unsigned format)
|
|
unsigned Texture::GetSRVFormat(unsigned format)
|
|
|
{
|
|
{
|
|
|
if (format == DXGI_FORMAT_R24G8_TYPELESS)
|
|
if (format == DXGI_FORMAT_R24G8_TYPELESS)
|
|
@@ -424,18 +192,4 @@ unsigned Texture::GetSRGBFormat(unsigned format)
|
|
|
return format;
|
|
return format;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void Texture::CheckTextureBudget(StringHash type)
|
|
|
|
|
-{
|
|
|
|
|
- ResourceCache* cache = GetSubsystem<ResourceCache>();
|
|
|
|
|
- unsigned long long textureBudget = cache->GetMemoryBudget(type);
|
|
|
|
|
- unsigned long long textureUse = cache->GetMemoryUse(type);
|
|
|
|
|
- if (!textureBudget)
|
|
|
|
|
- return;
|
|
|
|
|
-
|
|
|
|
|
- // If textures are over the budget, they likely can not be freed directly as materials still refer to them.
|
|
|
|
|
- // Therefore free unused materials first
|
|
|
|
|
- if (textureUse > textureBudget)
|
|
|
|
|
- cache->ReleaseResources(Material::GetTypeStatic());
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
}
|
|
}
|