Browse Source

Initial Texture class refactoring. Get rid of API-specific Texture header.

Lasse Öörni 9 years ago
parent
commit
f452a16f2d

+ 9 - 255
Source/Urho3D/Graphics/Direct3D11/D3D11Texture.cpp

@@ -36,25 +36,6 @@
 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[] =
 {
     D3D11_FILTER_MIN_MAG_MIP_POINT,
@@ -75,136 +56,28 @@ static const D3D11_TEXTURE_ADDRESS_MODE d3dAddressMode[] =
     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)
 {
     if (graphics_)
         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
@@ -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()
 {
     if ((!parametersDirty_ && sampler_) || !object_.ptr_)
@@ -352,40 +154,6 @@ void Texture::UpdateParameters()
     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)
 {
     if (format == DXGI_FORMAT_R24G8_TYPELESS)
@@ -424,18 +192,4 @@ unsigned Texture::GetSRGBFormat(unsigned 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());
-}
-
 }

+ 0 - 191
Source/Urho3D/Graphics/Direct3D11/D3D11Texture.h

@@ -1,191 +0,0 @@
-//
-// Copyright (c) 2008-2016 the Urho3D project.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-#pragma once
-
-#include "../../Container/ArrayPtr.h"
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-#include "../../Math/Color.h"
-#include "../../Resource/Resource.h"
-
-namespace Urho3D
-{
-
-static const int MAX_TEXTURE_QUALITY_LEVELS = 3;
-
-class XMLElement;
-class XMLFile;
-
-/// Base class for texture resources.
-class URHO3D_API Texture : public Resource, public GPUObject
-{
-public:
-    /// Construct.
-    Texture(Context* context);
-    /// Destruct.
-    virtual ~Texture();
-
-    /// Set number of requested mip levels. Needs to be called before setting size.
-    void SetNumLevels(unsigned levels);
-    /// Set filtering mode.
-    void SetFilterMode(TextureFilterMode filter);
-    /// Set addressing mode by texture coordinate.
-    void SetAddressMode(TextureCoordinate coord, TextureAddressMode address);
-    /// Set shadow compare mode.
-    void SetShadowCompare(bool enable);
-    /// Set border color for border addressing mode.
-    void SetBorderColor(const Color& color);
-    /// Set sRGB sampling and writing mode.
-    void SetSRGB(bool enable);
-    /// Set backup texture to use when rendering to this texture.
-    void SetBackupTexture(Texture* texture);
-    /// Set mip levels to skip on a quality setting when loading. Ensures higher quality levels do not skip more.
-    void SetMipsToSkip(int quality, int toSkip);
-
-    /// Return texture format.
-    unsigned GetFormat() const { return format_; }
-
-    /// Return whether the texture format is compressed.
-    bool IsCompressed() const;
-
-    /// Return number of mip levels.
-    unsigned GetLevels() const { return levels_; }
-
-    /// Return width.
-    int GetWidth() const { return width_; }
-
-    /// Return height.
-    int GetHeight() const { return height_; }
-
-    /// Return height.
-    int GetDepth() const { return depth_; }
-
-    /// Return filtering mode.
-    TextureFilterMode GetFilterMode() const { return filterMode_; }
-
-    /// Return addressing mode by texture coordinate.
-    TextureAddressMode GetAddressMode(TextureCoordinate coord) const { return addressMode_[coord]; }
-
-    /// Return whether shadow compare is enabled.
-    bool GetShadowCompare() const { return shadowCompare_; }
-
-    /// Return border color.
-    const Color& GetBorderColor() const { return borderColor_; }
-
-    /// Return whether is using sRGB sampling and writing.
-    bool GetSRGB() const { return sRGB_; }
-
-    /// Return backup texture.
-    Texture* GetBackupTexture() const { return backupTexture_; }
-
-    /// Return mip levels to skip on a quality setting when loading.
-    int GetMipsToSkip(int quality) const;
-    /// Return mip level width, or 0 if level does not exist.
-    int GetLevelWidth(unsigned level) const;
-    /// Return mip level width, or 0 if level does not exist.
-    int GetLevelHeight(unsigned level) const;
-    /// Return mip level depth, or 0 if level does not exist.
-    int GetLevelDepth(unsigned level) const;
-
-    /// Return texture usage type.
-    TextureUsage GetUsage() const { return usage_; }
-
-    /// Return data size in bytes for a rectangular region.
-    unsigned GetDataSize(int width, int height) const;
-    /// Return data size in bytes for a volume region.
-    unsigned GetDataSize(int width, int height, int depth) const;
-    /// Return data size in bytes for a pixel or block row.
-    unsigned GetRowDataSize(int width) const;
-    /// Return number of image components required to receive pixel data from GetData(), or 0 for compressed images.
-    unsigned GetComponents() const;
-
-    /// Return whether the parameters are dirty.
-    bool GetParametersDirty() const { return parametersDirty_ || !sampler_; }
-
-    /// Set additional parameters from an XML file.
-    void SetParameters(XMLFile* xml);
-    /// Set additional parameters from an XML element.
-    void SetParameters(const XMLElement& element);
-    /// Mark parameters dirty. Called by Graphics.
-    void SetParametersDirty();
-    /// Create sampler state object after parameters have been changed. Called by Graphics when assigning the texture.
-    void UpdateParameters();
-
-    /// Return shader resource view.
-    void* GetShaderResourceView() const { return shaderResourceView_; }
-
-    /// Return sampler state object.
-    void* GetSampler() const { return sampler_; }
-
-    /// Check maximum allowed mip levels for a specific texture size.
-    static unsigned CheckMaxLevels(int width, int height, unsigned requestedLevels);
-    /// Check maximum allowed mip levels for a specific 3D texture size.
-    static unsigned CheckMaxLevels(int width, int height, int depth, unsigned requestedLevels);
-    /// Return the shader resource view format corresponding to a texture format. Handles conversion of typeless depth texture formats.
-    static unsigned GetSRVFormat(unsigned format);
-    /// Return the depth-stencil view format corresponding to a texture format. Handles conversion of typeless depth texture formats.
-    static unsigned GetDSVFormat(unsigned format);
-    /// Convert format to sRGB.
-    static unsigned GetSRGBFormat(unsigned format);
-
-protected:
-    /// Check whether texture memory budget has been exceeded. Free unused materials in that case to release the texture references.
-    void CheckTextureBudget(StringHash type);
-
-    /// Shader resource view.
-    void* shaderResourceView_;
-    /// Sampler state object.
-    void* sampler_;
-    /// Texture format.
-    unsigned format_;
-    /// Texture usage type.
-    TextureUsage usage_;
-    /// Current mip levels.
-    unsigned levels_;
-    /// Requested mip levels.
-    unsigned requestedLevels_;
-    /// Texture width.
-    int width_;
-    /// Texture height.
-    int height_;
-    /// Texture depth.
-    int depth_;
-    /// Shadow compare mode.
-    bool shadowCompare_;
-    /// Filtering mode.
-    TextureFilterMode filterMode_;
-    /// Addressing mode.
-    TextureAddressMode addressMode_[MAX_COORDS];
-    /// Mip levels to skip when loading per texture quality setting.
-    unsigned mipsToSkip_[MAX_TEXTURE_QUALITY_LEVELS];
-    /// Border color.
-    Color borderColor_;
-    /// sRGB sampling and writing mode flag.
-    bool sRGB_;
-    /// Parameters dirty flag.
-    bool parametersDirty_;
-    /// Backup texture.
-    SharedPtr<Texture> backupTexture_;
-};
-
-}

+ 2 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9IndexBuffer.cpp

@@ -240,12 +240,12 @@ bool IndexBuffer::Create()
         }
 
         unsigned pool = dynamic_ ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
-        unsigned usage = dynamic_ ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0;
+        unsigned d3dUsage = dynamic_ ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0;
 
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         HRESULT hr = device->CreateIndexBuffer(
             indexCount_ * indexSize_,
-            usage,
+            d3dUsage,
             indexSize_ == sizeof(unsigned) ? D3DFMT_INDEX32 : D3DFMT_INDEX16,
             (D3DPOOL)pool,
             (IDirect3DIndexBuffer9**)&object_,

+ 4 - 217
Source/Urho3D/Graphics/Direct3D9/D3D9Texture.cpp

@@ -35,76 +35,6 @@
 namespace Urho3D
 {
 
-static const char* addressModeNames[] =
-{
-    "wrap",
-    "mirror",
-    "clamp",
-    "border",
-    0
-};
-
-static const char* filterModeNames[] =
-{
-    "nearest",
-    "bilinear",
-    "trilinear",
-    "anisotropic",
-    "default",
-    0
-};
-
-Texture::Texture(Context* context) :
-    Resource(context),
-    GPUObject(GetSubsystem<Graphics>()),
-    format_(D3DFMT_UNKNOWN),
-    pool_(D3DPOOL_MANAGED),
-    usage_(0),
-    levels_(0),
-    requestedLevels_(0),
-    width_(0),
-    height_(0),
-    depth_(0),
-    filterMode_(FILTER_DEFAULT),
-    sRGB_(false)
-{
-    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_ & D3DUSAGE_DEPTHSTENCIL)
-        requestedLevels_ = 1;
-    else
-        requestedLevels_ = levels;
-}
-
-void Texture::SetFilterMode(TextureFilterMode mode)
-{
-    filterMode_ = mode;
-}
-
-void Texture::SetAddressMode(TextureCoordinate coord, TextureAddressMode mode)
-{
-    addressMode_[coord] = mode;
-}
-
-void Texture::SetShadowCompare(bool /*enable*/)
-{
-}
-
-void Texture::SetBorderColor(const Color& color)
-{
-    borderColor_ = color;
-}
-
 void Texture::SetSRGB(bool enable)
 {
     if (graphics_)
@@ -113,24 +43,14 @@ void Texture::SetSRGB(bool enable)
     sRGB_ = enable;
 }
 
-void Texture::SetBackupTexture(Texture* texture)
+void Texture::UpdateParameters()
 {
-    backupTexture_ = texture;
+    // No-op on Direct3D9, handled by Graphics instead by modifying the sampler settings as necessary
 }
 
-void Texture::SetMipsToSkip(int quality, int toSkip)
+bool Texture::GetParametersDirty() const
 {
-    if (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS)
-    {
-        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];
-        }
-    }
+    return false;
 }
 
 bool Texture::IsCompressed() const
@@ -138,59 +58,6 @@ bool Texture::IsCompressed() const
     return format_ == D3DFMT_DXT1 || format_ == D3DFMT_DXT3 || format_ == D3DFMT_DXT5;
 }
 
-int Texture::GetMipsToSkip(int quality) const
-{
-    return (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS) ? mipsToSkip_[quality] : 0;
-}
-
-int Texture::GetLevelWidth(unsigned level) 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);
-}
-
-TextureUsage Texture::GetUsage() const
-{
-    if (usage_ & D3DUSAGE_DEPTHSTENCIL)
-        return TEXTURE_DEPTHSTENCIL;
-
-    if (usage_ & D3DUSAGE_RENDERTARGET)
-        return TEXTURE_RENDERTARGET;
-
-    if (pool_ == D3DPOOL_DEFAULT)
-        return TEXTURE_DYNAMIC;
-
-    return TEXTURE_STATIC;
-}
-
-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
-{
-    return depth * GetDataSize(width, height);
-}
-
 unsigned Texture::GetRowDataSize(int width) const
 {
     switch (format_)
@@ -237,84 +104,4 @@ 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::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());
-}
-
 }

+ 0 - 160
Source/Urho3D/Graphics/Direct3D9/D3D9Texture.h

@@ -1,160 +0,0 @@
-//
-// Copyright (c) 2008-2016 the Urho3D project.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-#pragma once
-
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-#include "../../Math/Color.h"
-#include "../../Resource/Resource.h"
-
-namespace Urho3D
-{
-
-static const int MAX_TEXTURE_QUALITY_LEVELS = 3;
-
-class XMLElement;
-class XMLFile;
-
-/// Base class for texture resources.
-class URHO3D_API Texture : public Resource, public GPUObject
-{
-public:
-    /// Construct.
-    Texture(Context* context);
-    /// Destruct.
-    virtual ~Texture();
-
-    /// Set number of requested mip levels. Needs to be called before setting size.
-    void SetNumLevels(unsigned levels);
-    /// Set filtering mode.
-    void SetFilterMode(TextureFilterMode filter);
-    /// Set addressing mode by texture coordinate.
-    void SetAddressMode(TextureCoordinate coord, TextureAddressMode address);
-
-    /// Set shadow compare mode. No-op on D3D9.
-    void SetShadowCompare(bool enable);
-
-    /// Set border color for border addressing mode.
-    void SetBorderColor(const Color& color);
-    /// Set sRGB sampling and writing mode.
-    void SetSRGB(bool enable);
-    /// Set backup texture to use when rendering to this texture.
-    void SetBackupTexture(Texture* texture);
-    /// Set mip levels to skip on a quality setting when loading. Ensures higher quality levels do not skip more.
-    void SetMipsToSkip(int quality, int toSkip);
-
-    /// Return texture format.
-    unsigned GetFormat() const { return format_; }
-
-    /// Return whether the texture format is compressed.
-    bool IsCompressed() const;
-
-    /// Return number of mip levels.
-    unsigned GetLevels() const { return levels_; }
-
-    /// Return width.
-    int GetWidth() const { return width_; }
-
-    /// Return height.
-    int GetHeight() const { return height_; }
-
-    /// Return height.
-    int GetDepth() const { return depth_; }
-
-    /// Return filtering mode.
-    TextureFilterMode GetFilterMode() const { return filterMode_; }
-
-    /// Return addressing mode by texture coordinate.
-    TextureAddressMode GetAddressMode(TextureCoordinate coord) const { return addressMode_[coord]; }
-
-    /// Return whether shadow compare is enabled. Always false on D3D9.
-    bool GetShadowCompare() const { return false; }
-
-    /// Return border color.
-    const Color& GetBorderColor() const { return borderColor_; }
-
-    /// Return whether is using sRGB sampling and writing.
-    bool GetSRGB() const { return sRGB_; }
-
-    /// Return backup texture.
-    Texture* GetBackupTexture() const { return backupTexture_; }
-
-    /// Return mip levels to skip on a quality setting when loading.
-    int GetMipsToSkip(int quality) const;
-    /// Return mip level width, or 0 if level does not exist.
-    int GetLevelWidth(unsigned level) const;
-    /// Return mip level width, or 0 if level does not exist.
-    int GetLevelHeight(unsigned level) const;
-    /// Return mip level depth, or 0 if level does not exist.
-    int GetLevelDepth(unsigned level) const;
-    /// Return texture usage type.
-    TextureUsage GetUsage() const;
-    /// Return data size in bytes for a rectangular region.
-    unsigned GetDataSize(int width, int height) const;
-    /// Return data size in bytes for a volume region.
-    unsigned GetDataSize(int width, int height, int depth) const;
-    /// Return data size in bytes for a pixel or block row.
-    unsigned GetRowDataSize(int width) const;
-    /// Return number of image components required to receive pixel data from GetData(), or 0 for compressed images.
-    unsigned GetComponents() const;
-
-    /// Set additional parameters from an XML file.
-    void SetParameters(XMLFile* xml);
-    /// Set additional parameters from an XML element.
-    void SetParameters(const XMLElement& element);
-
-protected:
-    /// Check whether texture memory budget has been exceeded. Free unused materials in that case to release the texture references.
-    void CheckTextureBudget(StringHash type);
-
-    /// Texture format.
-    unsigned format_;
-    /// Memory pool.
-    unsigned pool_;
-    /// Texture usage type.
-    unsigned usage_;
-    /// Current mip levels.
-    unsigned levels_;
-    /// Requested mip levels.
-    unsigned requestedLevels_;
-    /// Texture width.
-    int width_;
-    /// Texture height.
-    int height_;
-    /// Texture depth.
-    int depth_;
-    /// Filtering mode.
-    TextureFilterMode filterMode_;
-    /// Addressing mode.
-    TextureAddressMode addressMode_[MAX_COORDS];
-    /// Mip levels to skip when loading per texture quality setting.
-    unsigned mipsToSkip_[MAX_TEXTURE_QUALITY_LEVELS];
-    /// Border color.
-    Color borderColor_;
-    /// sRGB sampling and writing mode flag.
-    bool sRGB_;
-    /// Backup texture.
-    SharedPtr<Texture> backupTexture_;
-};
-
-}

+ 26 - 19
Source/Urho3D/Graphics/Direct3D9/D3D9Texture2D.cpp

@@ -108,13 +108,13 @@ bool Texture2D::EndLoad()
 
 void Texture2D::OnDeviceLost()
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    if (usage_ > TEXTURE_STATIC)
         Release();
 }
 
 void Texture2D::OnDeviceReset()
 {
-    if (pool_ == D3DPOOL_DEFAULT || !object_.ptr_ || dataPending_)
+    if (usage_ > TEXTURE_STATIC || !object_.ptr_ || dataPending_)
     {
         // If has a resource file, reload through the resource cache. Otherwise just recreate.
         ResourceCache* cache = GetSubsystem<ResourceCache>();
@@ -158,17 +158,10 @@ bool Texture2D::SetSize(int width, int height, unsigned format, TextureUsage usa
 
     // Delete the old rendersurface if any
     renderSurface_.Reset();
-    pool_ = D3DPOOL_MANAGED;
-    usage_ = 0;
 
     if (usage == TEXTURE_RENDERTARGET || usage == TEXTURE_DEPTHSTENCIL)
     {
         renderSurface_ = new RenderSurface(this);
-        if (usage == TEXTURE_RENDERTARGET)
-            usage_ |= D3DUSAGE_RENDERTARGET;
-        else
-            usage_ |= D3DUSAGE_DEPTHSTENCIL;
-        pool_ = D3DPOOL_DEFAULT;
 
         // Clamp mode addressing by default, nearest filtering, and mipmaps disabled
         addressMode_[COORD_U] = ADDRESS_CLAMP;
@@ -176,11 +169,6 @@ bool Texture2D::SetSize(int width, int height, unsigned format, TextureUsage usa
         filterMode_ = FILTER_NEAREST;
         requestedLevels_ = 1;
     }
-    else if (usage == TEXTURE_DYNAMIC)
-    {
-        usage_ |= D3DUSAGE_DYNAMIC;
-        pool_ = D3DPOOL_DEFAULT;
-    }
 
     if (usage == TEXTURE_RENDERTARGET)
         SubscribeToEvent(E_RENDERSURFACEUPDATE, URHO3D_HANDLER(Texture2D, HandleRenderSurfaceUpdate));
@@ -190,6 +178,7 @@ bool Texture2D::SetSize(int width, int height, unsigned format, TextureUsage usa
     width_ = width;
     height_ = height;
     format_ = format;
+    usage_ = usage;
 
     return Create();
 }
@@ -245,7 +234,7 @@ bool Texture2D::SetData(unsigned level, int x, int y, int width, int height, con
     d3dRect.bottom = y + height;
 
     DWORD flags = 0;
-    if (level == 0 && x == 0 && y == 0 && width == levelWidth && height == levelHeight && pool_ == D3DPOOL_DEFAULT)
+    if (level == 0 && x == 0 && y == 0 && width == levelWidth && height == levelHeight && usage_ > TEXTURE_STATIC)
         flags |= D3DLOCK_DISCARD;
 
     HRESULT hr = ((IDirect3DTexture9*)object_.ptr_)->LockRect(level, &d3dLockedRect, (flags & D3DLOCK_DISCARD) ? 0 : &d3dRect, flags);
@@ -595,9 +584,27 @@ bool Texture2D::Create()
         return true;
     }
 
+    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;
+        break;
+    case TEXTURE_DEPTHSTENCIL:
+        d3dUsage |= D3DUSAGE_DEPTHSTENCIL;
+        break;
+    default:
+        break;
+    }
+
     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))
+    if (usage_ == TEXTURE_DEPTHSTENCIL && !graphics_->GetImpl()->CheckFormatSupport((D3DFORMAT)format_, d3dUsage, D3DRTYPE_TEXTURE))
     {
         HRESULT hr = device->CreateDepthStencilSurface(
             (UINT)width_,
@@ -623,9 +630,9 @@ bool Texture2D::Create()
             (UINT)width_,
             (UINT)height_,
             requestedLevels_,
-            usage_,
+            d3dUsage,
             (D3DFORMAT)format_,
-            (D3DPOOL)pool_,
+            (D3DPOOL)pool,
             (IDirect3DTexture9**)&object_,
             0);
         if (FAILED(hr))
@@ -637,7 +644,7 @@ bool Texture2D::Create()
 
         levels_ = ((IDirect3DTexture9*)object_.ptr_)->GetLevelCount();
 
-        if (usage_ & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))
+        if (usage_ >= TEXTURE_RENDERTARGET)
         {
             hr = ((IDirect3DTexture9*)object_.ptr_)->GetSurfaceLevel(0, (IDirect3DSurface9**)&renderSurface_->surface_);
             if (FAILED(hr))

+ 4 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9Texture2D.h

@@ -69,9 +69,11 @@ public:
     /// Return render surface.
     RenderSurface* GetRenderSurface() const { return renderSurface_; }
 
+protected:
+    /// Create the GPU texture.
+    virtual bool Create();
+
 private:
-    /// Create texture.
-    bool Create();
     /// Handle render surface update event.
     void HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData);
 

+ 2 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9Texture2DArray.cpp

@@ -134,13 +134,13 @@ bool Texture2DArray::EndLoad()
 
 void Texture2DArray::OnDeviceLost()
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    if (usage_ > TEXTURE_STATIC)
         Release();
 }
 
 void Texture2DArray::OnDeviceReset()
 {
-    if (pool_ == D3DPOOL_DEFAULT || !object_.ptr_ || dataPending_)
+    if (usage_ > TEXTURE_STATIC || !object_.ptr_ || dataPending_)
     {
         // If has a resource file, reload through the resource cache. Otherwise just recreate.
         ResourceCache* cache = GetSubsystem<ResourceCache>();

+ 4 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9Texture2DArray.h

@@ -74,9 +74,11 @@ public:
     /// Return render surface.
     RenderSurface* GetRenderSurface() const { return renderSurface_; }
 
+protected:
+    /// Create the GPU texture.
+    virtual bool Create();
+
 private:
-    /// Create texture array.
-    bool Create();
     /// Handle render surface update event.
     void HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData);
 

+ 9 - 14
Source/Urho3D/Graphics/Direct3D9/D3D9Texture3D.cpp

@@ -152,13 +152,13 @@ bool Texture3D::EndLoad()
 
 void Texture3D::OnDeviceLost()
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    if (usage_ > TEXTURE_STATIC)
         Release();
 }
 
 void Texture3D::OnDeviceReset()
 {
-    if (pool_ == D3DPOOL_DEFAULT || !object_.ptr_ || dataPending_)
+    if (usage_ > TEXTURE_STATIC || !object_.ptr_ || dataPending_)
     {
         // If has a resource file, reload through the resource cache. Otherwise just recreate.
         ResourceCache* cache = GetSubsystem<ResourceCache>();
@@ -202,19 +202,11 @@ bool Texture3D::SetSize(int width, int height, int depth, unsigned format, Textu
         return false;
     }
 
-    pool_ = D3DPOOL_MANAGED;
-    usage_ = 0;
-
-    if (usage == TEXTURE_DYNAMIC)
-    {
-        usage_ |= D3DUSAGE_DYNAMIC;
-        pool_ = D3DPOOL_DEFAULT;
-    }
-
     width_ = width;
     height_ = height;
     depth_ = depth;
     format_ = format;
+    usage_ = usage;
 
     return Create();
 }
@@ -275,7 +267,7 @@ bool Texture3D::SetData(unsigned level, int x, int y, int z, int width, int heig
 
     DWORD flags = 0;
     if (level == 0 && x == 0 && y == 0 && z == 0 && width == levelWidth && height == levelHeight && depth == levelDepth &&
-        pool_ == D3DPOOL_DEFAULT)
+        usage_ > TEXTURE_STATIC)
         flags |= D3DLOCK_DISCARD;
 
     HRESULT hr = ((IDirect3DVolumeTexture9*)object_.ptr_)->LockBox(level, &d3dLockedBox, (flags & D3DLOCK_DISCARD) ? 0 : &d3dBox, flags);
@@ -610,15 +602,18 @@ bool Texture3D::Create()
         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_,
-        usage_,
+        d3dUsage,
         (D3DFORMAT)format_,
-        (D3DPOOL)pool_,
+        (D3DPOOL)pool,
         (IDirect3DVolumeTexture9**)&object_,
         0);
     if (FAILED(hr))

+ 4 - 3
Source/Urho3D/Graphics/Direct3D9/D3D9Texture3D.h

@@ -65,10 +65,11 @@ public:
     /// Get data from a mip level. The destination buffer must be big enough. Return true if successful.
     bool GetData(unsigned level, void* dest) const;
 
-private:
-    /// Create texture.
-    bool Create();
+protected:
+    /// Create the GPU texture.
+    virtual bool Create();
 
+private:
     /// Image file acquired during BeginLoad.
     SharedPtr<Image> loadImage_;
     /// Parameter file acquired during BeginLoad.

+ 22 - 17
Source/Urho3D/Graphics/Direct3D9/D3D9TextureCube.cpp

@@ -254,13 +254,13 @@ bool TextureCube::EndLoad()
 
 void TextureCube::OnDeviceLost()
 {
-    if (pool_ == D3DPOOL_DEFAULT)
+    if (usage_ > TEXTURE_STATIC)
         Release();
 }
 
 void TextureCube::OnDeviceReset()
 {
-    if (pool_ == D3DPOOL_DEFAULT || !object_.ptr_ || dataPending_)
+    if (usage_ > TEXTURE_STATIC || !object_.ptr_ || dataPending_)
     {
         // If has a resource file, reload through the resource cache. Otherwise just recreate.
         ResourceCache* cache = GetSubsystem<ResourceCache>();
@@ -317,26 +317,15 @@ bool TextureCube::SetSize(int size, unsigned format, TextureUsage usage)
         faceMemoryUse_[i] = 0;
     }
 
-    pool_ = D3DPOOL_MANAGED;
-    usage_ = 0;
-
     if (usage == TEXTURE_RENDERTARGET)
     {
         for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
             renderSurfaces_[i] = new RenderSurface(this);
 
-        usage_ |= D3DUSAGE_RENDERTARGET;
-        pool_ = D3DPOOL_DEFAULT;
-
         // Nearest filtering and mipmaps disabled by default
         filterMode_ = FILTER_NEAREST;
         requestedLevels_ = 1;
     }
-    else if (usage == TEXTURE_DYNAMIC)
-    {
-        usage_ |= D3DUSAGE_DYNAMIC;
-        pool_ = D3DPOOL_DEFAULT;
-    }
 
     if (usage == TEXTURE_RENDERTARGET)
         SubscribeToEvent(E_RENDERSURFACEUPDATE, URHO3D_HANDLER(TextureCube, HandleRenderSurfaceUpdate));
@@ -346,6 +335,7 @@ bool TextureCube::SetSize(int size, unsigned format, TextureUsage usage)
     width_ = size;
     height_ = size;
     format_ = format;
+    usage_ = usage;
 
     return Create();
 }
@@ -401,7 +391,7 @@ bool TextureCube::SetData(CubeMapFace face, unsigned level, int x, int y, int wi
     d3dRect.bottom = y + height;
 
     DWORD flags = 0;
-    if (level == 0 && x == 0 && y == 0 && width == levelWidth && height == levelHeight && pool_ == D3DPOOL_DEFAULT)
+    if (level == 0 && x == 0 && y == 0 && width == levelWidth && height == levelHeight && usage_ > TEXTURE_STATIC)
         flags |= D3DLOCK_DISCARD;
 
     HRESULT hr = ((IDirect3DCubeTexture9*)object_.ptr_)->LockRect((D3DCUBEMAP_FACES)face, level, &d3dLockedRect,
@@ -810,13 +800,28 @@ bool TextureCube::Create()
         return true;
     }
 
+    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;
+        break;
+    default:
+        break;
+    }
+
     IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
     HRESULT hr = device->CreateCubeTexture(
         (UINT)width_,
         requestedLevels_,
-        usage_,
+        d3dUsage,
         (D3DFORMAT)format_,
-        (D3DPOOL)pool_,
+        (D3DPOOL)pool,
         (IDirect3DCubeTexture9**)&object_.ptr_,
         0);
     if (FAILED(hr))
@@ -828,7 +833,7 @@ bool TextureCube::Create()
 
     levels_ = ((IDirect3DCubeTexture9*)object_.ptr_)->GetLevelCount();
 
-    if (usage_ & D3DUSAGE_RENDERTARGET)
+    if (usage_ == TEXTURE_RENDERTARGET)
     {
         for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
         {

+ 4 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9TextureCube.h

@@ -71,9 +71,11 @@ public:
     /// Return render surface for one face.
     RenderSurface* GetRenderSurface(CubeMapFace face) const { return renderSurfaces_[face]; }
 
+protected:
+    /// Create the GPU texture.
+    virtual bool Create();
+
 private:
-    /// Create texture.
-    bool Create();
     /// Handle render surface update event.
     void HandleRenderSurfaceUpdate(StringHash eventType, VariantMap& eventData);
 

+ 2 - 2
Source/Urho3D/Graphics/Direct3D9/D3D9VertexBuffer.cpp

@@ -245,12 +245,12 @@ bool VertexBuffer::Create()
         }
 
         unsigned pool = dynamic_ ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
-        unsigned usage = dynamic_ ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0;
+        unsigned d3dUsage = dynamic_ ? D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY : 0;
 
         IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
         HRESULT hr = device->CreateVertexBuffer(
             vertexCount_ * vertexSize_,
-            usage,
+            d3dUsage,
             0,
             (D3DPOOL)pool,
             (IDirect3DVertexBuffer9**)&object_.ptr_,

+ 2 - 221
Source/Urho3D/Graphics/OpenGL/OGLTexture.cpp

@@ -57,25 +57,6 @@ static GLenum gl3WrapModes[] =
 };
 #endif
 
-static const char* addressModeNames[] =
-{
-    "wrap",
-    "mirror",
-    "clamp",
-    "border",
-    0
-};
-
-static const char* filterModeNames[] =
-{
-    "nearest",
-    "bilinear",
-    "trilinear",
-    "anisotropic",
-    "default",
-    0
-};
-
 static GLenum GetWrapMode(TextureAddressMode mode)
 {
 #ifndef GL_ES_VERSION_2_0
@@ -85,60 +66,6 @@ static GLenum GetWrapMode(TextureAddressMode mode)
 #endif
 }
 
-Texture::Texture(Context* context) :
-    Resource(context),
-    GPUObject(GetSubsystem<Graphics>()),
-    usage_(TEXTURE_STATIC),
-    format_(0),
-    levels_(0),
-    requestedLevels_(0),
-    width_(0),
-    height_(0),
-    depth_(0),
-    shadowCompare_(false),
-    parametersDirty_(true),
-    filterMode_(FILTER_DEFAULT),
-    sRGB_(false)
-{
-    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)
-{
-    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)
 {
     if (graphics_)
@@ -157,31 +84,6 @@ void Texture::SetSRGB(bool enable)
     }
 }
 
-void Texture::SetBackupTexture(Texture* texture)
-{
-    backupTexture_ = texture;
-}
-
-void Texture::SetMipsToSkip(int quality, int toSkip)
-{
-    if (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS)
-    {
-        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];
-        }
-    }
-}
-
-void Texture::SetParametersDirty()
-{
-    parametersDirty_ = true;
-}
-
 void Texture::UpdateParameters()
 {
     if (!object_.name_ || !graphics_)
@@ -250,9 +152,9 @@ void Texture::UpdateParameters()
     parametersDirty_ = false;
 }
 
-int Texture::GetMipsToSkip(int quality) const
+bool Texture::GetParametersDirty() const
 {
-    return (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS) ? mipsToSkip_[quality] : 0;
+    return parametersDirty_;
 }
 
 bool Texture::IsCompressed() const
@@ -263,47 +165,6 @@ bool Texture::IsCompressed() const
            format_ == COMPRESSED_RGB_PVRTC_2BPPV1_IMG || format_ == COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
 }
 
-int Texture::GetLevelWidth(unsigned level) 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);
-}
-
-unsigned Texture::GetDataSize(int width, int height) const
-{
-    if (IsCompressed())
-    {
-        if (format_ == COMPRESSED_RGB_PVRTC_4BPPV1_IMG || format_ == COMPRESSED_RGBA_PVRTC_4BPPV1_IMG)
-            return (unsigned)((Max(width, 8) * Max(height, 8) * 4 + 7) >> 3);
-        else if (format_ == COMPRESSED_RGB_PVRTC_2BPPV1_IMG || format_ == COMPRESSED_RGBA_PVRTC_2BPPV1_IMG)
-            return (unsigned)((Max(width, 16) * Max(height, 8) * 2 + 7) >> 3);
-        else
-            return GetRowDataSize(width) * ((height + 3) >> 2);
-    }
-    else
-        return GetRowDataSize(width) * height;
-}
-
-unsigned Texture::GetDataSize(int width, int height, int depth) const
-{
-    return depth * GetDataSize(width, height);
-}
-
 unsigned Texture::GetRowDataSize(int width) const
 {
     switch (format_)
@@ -366,14 +227,6 @@ unsigned Texture::GetRowDataSize(int width) const
     }
 }
 
-unsigned Texture::GetComponents() const
-{
-    if (!width_ || IsCompressed())
-        return 0;
-    else
-        return GetRowDataSize(width_) / width_;
-}
-
 unsigned Texture::GetExternalFormat(unsigned format)
 {
 #ifndef GL_ES_VERSION_2_0
@@ -423,64 +276,6 @@ unsigned Texture::GetDataType(unsigned format)
 #endif
 }
 
-void Texture::SetParameters(XMLFile* file)
-{
-    if (!file)
-        return;
-
-    XMLElement rootElem = file->GetRoot();
-    SetParameters(rootElem);
-}
-
-void Texture::SetParameters(const XMLElement& elem)
-{
-    XMLElement paramElem = elem.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();
-    }
-}
-
 unsigned Texture::GetSRGBFormat(unsigned format)
 {
 #ifndef GL_ES_VERSION_2_0
@@ -511,18 +306,4 @@ unsigned Texture::GetSRGBFormat(unsigned format)
 #endif
 }
 
-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());
-}
-
 }

+ 0 - 183
Source/Urho3D/Graphics/OpenGL/OGLTexture.h

@@ -1,183 +0,0 @@
-//
-// Copyright (c) 2008-2016 the Urho3D project.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-#pragma once
-
-#include "../../Graphics/GPUObject.h"
-#include "../../Graphics/GraphicsDefs.h"
-#include "../../Math/Color.h"
-#include "../../Resource/Resource.h"
-
-namespace Urho3D
-{
-
-static const int MAX_TEXTURE_QUALITY_LEVELS = 3;
-
-class XMLElement;
-class XMLFile;
-
-/// Base class for texture resources.
-class URHO3D_API Texture : public Resource, public GPUObject
-{
-public:
-    /// Construct.
-    Texture(Context* context);
-    /// Destruct.
-    virtual ~Texture();
-
-    /// Set number of requested mip levels. Needs to be called before setting size.
-    void SetNumLevels(unsigned levels);
-    /// Set filtering mode.
-    void SetFilterMode(TextureFilterMode filter);
-    /// Set addressing mode by texture coordinate.
-    void SetAddressMode(TextureCoordinate coord, TextureAddressMode address);
-    /// Set shadow compare mode.
-    void SetShadowCompare(bool enable);
-    /// Set border color for border addressing mode.
-    void SetBorderColor(const Color& color);
-    /// Set sRGB sampling and writing mode.
-    void SetSRGB(bool enable);
-    /// Set backup texture to use when rendering to this texture.
-    void SetBackupTexture(Texture* texture);
-    /// Set mip levels to skip on a quality setting when loading. Ensures higher quality levels do not skip more.
-    void SetMipsToSkip(int quality, int toSkip);
-    /// Dirty the parameters.
-    void SetParametersDirty();
-    /// Update changed parameters to OpenGL. Called by Graphics when binding the texture.
-    void UpdateParameters();
-
-    /// Return texture's OpenGL target.
-    unsigned GetTarget() const { return target_; }
-
-    /// Return texture format.
-    unsigned GetFormat() const { return format_; }
-
-    /// Return whether the texture format is compressed.
-    bool IsCompressed() const;
-
-    /// Return number of mip levels.
-    unsigned GetLevels() const { return levels_; }
-
-    /// Return width.
-    int GetWidth() const { return width_; }
-
-    /// Return height.
-    int GetHeight() const { return height_; }
-
-    /// Return height.
-    int GetDepth() const { return depth_; }
-
-    /// Return whether parameters are dirty.
-    bool GetParametersDirty() const { return parametersDirty_; }
-
-    /// Return filtering mode.
-    TextureFilterMode GetFilterMode() const { return filterMode_; }
-
-    /// Return addressing mode by texture coordinate.
-    TextureAddressMode GetAddressMode(TextureCoordinate coord) const { return addressMode_[coord]; }
-
-    /// Return whether shadow compare is enabled.
-    bool GetShadowCompare() const { return shadowCompare_; }
-
-    /// Return border color.
-    const Color& GetBorderColor() const { return borderColor_; }
-
-    /// Return whether is using sRGB sampling and writing.
-    bool GetSRGB() const { return sRGB_; }
-
-    /// Return backup texture.
-    Texture* GetBackupTexture() const { return backupTexture_; }
-
-    /// Return mip levels to skip on a quality setting when loading.
-    int GetMipsToSkip(int quality) const;
-    /// Return mip level width, or 0 if level does not exist.
-    int GetLevelWidth(unsigned level) const;
-    /// Return mip level width, or 0 if level does not exist.
-    int GetLevelHeight(unsigned level) const;
-    /// Return mip level depth, or 0 if level does not exist.
-    int GetLevelDepth(unsigned level) const;
-
-    /// Return texture usage type.
-    TextureUsage GetUsage() const { return usage_; }
-
-    /// Return data size in bytes for a rectangular region.
-    unsigned GetDataSize(int width, int height) const;
-    /// Return data size in bytes for a volume region.
-    unsigned GetDataSize(int width, int height, int depth) const;
-    /// Return data size in bytes for a pixel or block row.
-    unsigned GetRowDataSize(int width) const;
-    /// Return number of image components required to receive pixel data from GetData(), or 0 for compressed images.
-    unsigned GetComponents() const;
-    /// Return the non-internal texture format corresponding to an OpenGL internal format.
-    static unsigned GetExternalFormat(unsigned format);
-    /// Return the data type corresponding to an OpenGL internal format.
-    static unsigned GetDataType(unsigned format);
-
-    /// Set additional parameters from an XML file.
-    void SetParameters(XMLFile* xml);
-    /// Set additional parameters from an XML element.
-    void SetParameters(const XMLElement& element);
-    /// Return the corresponding SRGB texture format if supported. If not supported, return format unchanged.
-    unsigned GetSRGBFormat(unsigned format);
-
-protected:
-    /// Check whether texture memory budget has been exceeded. Free unused materials in that case to release the texture references.
-    void CheckTextureBudget(StringHash type);
-
-    /// Create texture.
-    virtual bool Create() { return true; }
-
-    /// Texture usage type.
-    TextureUsage usage_;
-    /// OpenGL target.
-    unsigned target_;
-    /// Texture format.
-    unsigned format_;
-    /// Current mip levels.
-    unsigned levels_;
-    /// Requested mip levels.
-    unsigned requestedLevels_;
-    /// Texture width.
-    int width_;
-    /// Texture height.
-    int height_;
-    /// Texture depth.
-    int depth_;
-    /// Shadow compare mode.
-    bool shadowCompare_;
-    /// Parameters dirty flag.
-    bool parametersDirty_;
-    /// Filtering mode.
-    TextureFilterMode filterMode_;
-    /// Addressing mode.
-    TextureAddressMode addressMode_[MAX_COORDS];
-    /// Mip levels to skip when loading per texture quality setting.
-    unsigned mipsToSkip_[MAX_TEXTURE_QUALITY_LEVELS];
-    /// Border color.
-    Color borderColor_;
-    /// sRGB sampling and writing mode flag.
-    bool sRGB_;
-    /// Backup texture.
-    SharedPtr<Texture> backupTexture_;
-};
-
-}

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLTexture2D.h

@@ -70,7 +70,7 @@ public:
     RenderSurface* GetRenderSurface() const { return renderSurface_; }
 
 protected:
-    /// Create texture.
+    /// Create the GPU texture.
     virtual bool Create();
 
 private:

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLTexture2DArray.h

@@ -75,7 +75,7 @@ public:
     RenderSurface* GetRenderSurface() const { return renderSurface_; }
 
 protected:
-    /// Create texture array.
+    /// Create the GPU texture.
     virtual bool Create();
 
 private:

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLTexture3D.h

@@ -65,7 +65,7 @@ public:
     bool GetData(unsigned level, void* dest) const;
 
 protected:
-    /// Create texture.
+    /// Create the GPU texture.
     virtual bool Create();
 
 private:

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLTextureCube.h

@@ -72,7 +72,7 @@ public:
     RenderSurface* GetRenderSurface(CubeMapFace face) const { return renderSurfaces_[face]; }
 
 protected:
-    /// Create texture.
+    /// Create the GPU texture.
     virtual bool Create();
 
 private:

+ 293 - 0
Source/Urho3D/Graphics/Texture.cpp

@@ -0,0 +1,293 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "../Precompiled.h"
+
+#include "../Graphics/Graphics.h"
+#include "../Graphics/GraphicsImpl.h"
+#include "../Graphics/Material.h"
+#include "../IO/FileSystem.h"
+#include "../IO/Log.h"
+#include "../Resource/ResourceCache.h"
+#include "../Resource/XMLFile.h"
+
+#include "../DebugNew.h"
+
+namespace Urho3D
+{
+
+static const char* addressModeNames[] =
+{
+    "wrap",
+    "mirror",
+    "clamp",
+    "border",
+    0
+};
+
+static const char* filterModeNames[] =
+{
+    "nearest",
+    "bilinear",
+    "trilinear",
+    "anisotropic",
+    "default",
+    0
+};
+
+Texture::Texture(Context* context) :
+    Resource(context),
+    GPUObject(GetSubsystem<Graphics>()),
+    shaderResourceView_(0),
+    sampler_(0),
+    format_(0),
+    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::SetBackupTexture(Texture* texture)
+{
+    backupTexture_ = texture;
+}
+
+void Texture::SetMipsToSkip(int quality, int toSkip)
+{
+    if (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS)
+    {
+        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];
+        }
+    }
+}
+
+int Texture::GetMipsToSkip(int quality) const
+{
+    return (quality >= QUALITY_LOW && quality < MAX_TEXTURE_QUALITY_LEVELS) ? mipsToSkip_[quality] : 0;
+}
+
+int Texture::GetLevelWidth(unsigned level) 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);
+}
+
+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
+{
+    return depth * GetDataSize(width, height);
+}
+
+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;
+}
+
+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;
+}
+
+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());
+}
+
+}

+ 183 - 7
Source/Urho3D/Graphics/Texture.h

@@ -22,10 +22,186 @@
 
 #pragma once
 
-#if defined(URHO3D_OPENGL)
-#include "OpenGL/OGLTexture.h"
-#elif defined(URHO3D_D3D11)
-#include "Direct3D11/D3D11Texture.h"
-#else
-#include "Direct3D9/D3D9Texture.h"
-#endif
+#include "../Graphics/GPUObject.h"
+#include "../Graphics/GraphicsDefs.h"
+#include "../Math/Color.h"
+#include "../Resource/Resource.h"
+
+namespace Urho3D
+{
+
+static const int MAX_TEXTURE_QUALITY_LEVELS = 3;
+
+class XMLElement;
+class XMLFile;
+
+/// Base class for texture resources.
+class URHO3D_API Texture : public Resource, public GPUObject
+{
+public:
+    /// Construct.
+    Texture(Context* context);
+    /// Destruct.
+    virtual ~Texture();
+
+    /// Set number of requested mip levels. Needs to be called before setting size.
+    void SetNumLevels(unsigned levels);
+    /// Set filtering mode.
+    void SetFilterMode(TextureFilterMode filter);
+    /// Set addressing mode by texture coordinate.
+    void SetAddressMode(TextureCoordinate coord, TextureAddressMode address);
+    /// Set shadow compare mode. Not used on Direct3D9.
+    void SetShadowCompare(bool enable);
+    /// Set border color for border addressing mode.
+    void SetBorderColor(const Color& color);
+    /// Set sRGB sampling and writing mode.
+    void SetSRGB(bool enable);
+    /// Set backup texture to use when rendering to this texture.
+    void SetBackupTexture(Texture* texture);
+    /// Set mip levels to skip on a quality setting when loading. Ensures higher quality levels do not skip more.
+    void SetMipsToSkip(int quality, int toSkip);
+
+    /// Return API-specific texture format.
+    unsigned GetFormat() const { return format_; }
+
+    /// Return whether the texture format is compressed.
+    bool IsCompressed() const;
+
+    /// Return number of mip levels.
+    unsigned GetLevels() const { return levels_; }
+
+    /// Return width.
+    int GetWidth() const { return width_; }
+
+    /// Return height.
+    int GetHeight() const { return height_; }
+
+    /// Return height.
+    int GetDepth() const { return depth_; }
+
+    /// Return filtering mode.
+    TextureFilterMode GetFilterMode() const { return filterMode_; }
+
+    /// Return addressing mode by texture coordinate.
+    TextureAddressMode GetAddressMode(TextureCoordinate coord) const { return addressMode_[coord]; }
+
+    /// Return whether shadow compare is enabled. Not used on Direct3D9.
+    bool GetShadowCompare() const { return shadowCompare_; }
+
+    /// Return border color.
+    const Color& GetBorderColor() const { return borderColor_; }
+
+    /// Return whether is using sRGB sampling and writing.
+    bool GetSRGB() const { return sRGB_; }
+
+    /// Return backup texture.
+    Texture* GetBackupTexture() const { return backupTexture_; }
+
+    /// Return mip levels to skip on a quality setting when loading.
+    int GetMipsToSkip(int quality) const;
+    /// Return mip level width, or 0 if level does not exist.
+    int GetLevelWidth(unsigned level) const;
+    /// Return mip level width, or 0 if level does not exist.
+    int GetLevelHeight(unsigned level) const;
+    /// Return mip level depth, or 0 if level does not exist.
+    int GetLevelDepth(unsigned level) const;
+
+    /// Return texture usage type.
+    TextureUsage GetUsage() const { return usage_; }
+
+    /// Return data size in bytes for a rectangular region.
+    unsigned GetDataSize(int width, int height) const;
+    /// Return data size in bytes for a volume region.
+    unsigned GetDataSize(int width, int height, int depth) const;
+    /// Return data size in bytes for a pixel or block row.
+    unsigned GetRowDataSize(int width) const;
+    /// Return number of image components required to receive pixel data from GetData(), or 0 for compressed images.
+    unsigned GetComponents() const;
+
+    /// Return whether the parameters are dirty.
+    bool GetParametersDirty() const;
+
+    /// Set additional parameters from an XML file.
+    void SetParameters(XMLFile* xml);
+    /// Set additional parameters from an XML element.
+    void SetParameters(const XMLElement& element);
+    /// Mark parameters dirty. Called by Graphics.
+    void SetParametersDirty();
+    /// Update dirty parameters to the texture object. Called by Graphics when assigning the texture.
+    void UpdateParameters();
+
+    /// Return shader resource view. Only used on Direct3D11.
+    void* GetShaderResourceView() const { return shaderResourceView_; }
+
+    /// Return sampler state object. Only used on Direct3D11.
+    void* GetSampler() const { return sampler_; }
+
+    /// Return texture's target. Only used on OpenGL.
+    unsigned GetTarget() const { return target_; }
+
+    /// Convert format to sRGB. Not used on Direct3D9.
+    unsigned GetSRGBFormat(unsigned format);
+
+    /// Check maximum allowed mip levels for a specific texture size.
+    static unsigned CheckMaxLevels(int width, int height, unsigned requestedLevels);
+    /// Check maximum allowed mip levels for a specific 3D texture size.
+    static unsigned CheckMaxLevels(int width, int height, int depth, unsigned requestedLevels);
+    /// Return the shader resource view format corresponding to a texture format. Handles conversion of typeless depth texture formats. Only used on Direct3D11.
+    static unsigned GetSRVFormat(unsigned format);
+    /// Return the depth-stencil view format corresponding to a texture format. Handles conversion of typeless depth texture formats. Only used on Direct3D11.
+    static unsigned GetDSVFormat(unsigned format);
+    /// Return the non-internal texture format corresponding to an OpenGL internal format.
+    static unsigned GetExternalFormat(unsigned format);
+    /// Return the data type corresponding to an OpenGL internal format.
+    static unsigned GetDataType(unsigned format);
+
+protected:
+    /// Check whether texture memory budget has been exceeded. Free unused materials in that case to release the texture references.
+    void CheckTextureBudget(StringHash type);
+    /// Create the GPU texture. Implemented in subclasses.
+    virtual bool Create() { return true; }
+
+    union
+    {
+        /// Direct3D11 shader resource view.
+        void* shaderResourceView_;
+        /// OpenGL target.
+        unsigned target_;
+    };
+
+    /// Direct3D11 sampler state object.
+    void* sampler_;
+
+    /// Texture format.
+    unsigned format_;
+    /// Texture usage type.
+    TextureUsage usage_;
+    /// Current mip levels.
+    unsigned levels_;
+    /// Requested mip levels.
+    unsigned requestedLevels_;
+    /// Texture width.
+    int width_;
+    /// Texture height.
+    int height_;
+    /// Texture depth.
+    int depth_;
+    /// Shadow compare mode.
+    bool shadowCompare_;
+    /// Filtering mode.
+    TextureFilterMode filterMode_;
+    /// Addressing mode.
+    TextureAddressMode addressMode_[MAX_COORDS];
+    /// Mip levels to skip when loading per texture quality setting.
+    unsigned mipsToSkip_[MAX_TEXTURE_QUALITY_LEVELS];
+    /// Border color.
+    Color borderColor_;
+    /// sRGB sampling and writing mode flag.
+    bool sRGB_;
+    /// Parameters dirty flag.
+    bool parametersDirty_;
+    /// Backup texture.
+    SharedPtr<Texture> backupTexture_;
+};
+
+}