// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "GPUTexture.h"
#include "ITextureOwner.h"
#include "Engine/Streaming/StreamableResource.h"
#include "Types.h"
///
/// GPU texture object which can change it's resolution (quality) at runtime
///
class FLAXENGINE_API StreamingTexture : public Object, public StreamableResource
{
friend class StreamTextureMipTask;
friend class StreamTextureResizeTask;
protected:
ITextureOwner* _owner;
GPUTexture* _texture;
TextureHeader _header;
volatile mutable int64 _streamingTasksCount;
bool _isBlockCompressed;
public:
///
/// Init
///
/// Parent object
/// Texture object name
StreamingTexture(ITextureOwner* owner, const String& name);
///
/// Destructor
///
~StreamingTexture();
public:
///
/// Gets the owner.
///
/// The owner.
FORCE_INLINE ITextureOwner* GetOwner() const
{
return _owner;
}
///
/// Gets texture object handle
///
/// Texture object
FORCE_INLINE GPUTexture* GetTexture() const
{
return _texture;
}
///
/// Gets texture size of Vector2::Zero if not loaded
///
/// Texture size
FORCE_INLINE Vector2 Size() const
{
return _texture->Size();
}
public:
///
/// Gets a value indicating whether this instance is initialized.
///
FORCE_INLINE bool IsInitialized() const
{
return _header.MipLevels > 0;
}
///
/// Gets total texture width (in texels)
///
/// Texture width
FORCE_INLINE int32 TotalWidth() const
{
return _header.Width;
}
///
/// Gets total texture height (in texels)
///
/// Texture width
FORCE_INLINE int32 TotalHeight() const
{
return _header.Height;
}
///
/// Gets total texture array size
///
/// Texture array size
FORCE_INLINE int32 TotalArraySize() const
{
return IsCubeMap() ? 6 : 1;
}
///
/// Gets total texture mip levels count
///
/// Texture mip levels
FORCE_INLINE int32 TotalMipLevels() const
{
return _header.MipLevels;
}
///
/// Returns texture format type
///
/// Texture format type
FORCE_INLINE TextureFormatType GetFormatType() const
{
return _header.Type;
}
///
/// Returns true if it's a cube map texture
///
/// True if i's a cubemap
FORCE_INLINE bool IsCubeMap() const
{
return _header.IsCubeMap;
}
///
/// Returns true if texture cannot be used during GPU resources streaming system
///
/// True if texture cannot be used during GPU resources streaming system
FORCE_INLINE bool NeverStream() const
{
return _header.NeverStream;
}
///
/// Gets the texture header.
///
/// Header
FORCE_INLINE const TextureHeader* GetHeader() const
{
return &_header;
}
///
/// Gets a boolean indicating whether this is a using a block compress format (BC1, BC2, BC3, BC4, BC5, BC6H, BC7).
///
FORCE_INLINE bool IsBlockCompressed() const
{
return _isBlockCompressed;
}
public:
///
/// Converts allocated texture mip index to the absolute mip map index.
///
/// Index of the texture mip.
/// The index of the mip map.
FORCE_INLINE int32 TextureMipIndexToTotalIndex(int32 textureMipIndex) const
{
const int32 missingMips = TotalMipLevels() - _texture->MipLevels();
return textureMipIndex + missingMips;
}
///
/// Converts absolute mip map index to the allocated texture mip index.
///
/// Index of the texture mip.
/// The index of the mip map.
FORCE_INLINE int32 TotalIndexToTextureMipIndex(int32 mipIndex) const
{
const int32 missingMips = TotalMipLevels() - _texture->MipLevels();
return mipIndex - missingMips;
}
public:
///
/// Creates new texture
///
/// Texture header
/// True if cannot create texture, otherwise false
bool Create(const TextureHeader& header);
///
/// Release texture
///
void UnloadTexture();
///
/// Gets the total memory usage that texture may have in use (if loaded to the maximum quality).
/// Exact value may differ due to memory alignment and resource allocation policy.
///
/// The amount of bytes.
uint64 GetTotalMemoryUsage() const;
public:
FORCE_INLINE GPUTexture* operator->() const
{
return _texture;
}
public:
// [Object]
String ToString() const override
{
return _texture->ToString();
}
// [StreamableResource]
int32 GetMaxResidency() const override
{
return _header.MipLevels;
}
int32 GetCurrentResidency() const override
{
return _texture->ResidentMipLevels();
}
int32 GetAllocatedResidency() const override
{
return _texture->MipLevels();
}
bool CanBeUpdated() const override;
Task* UpdateAllocation(int32 residency) override;
Task* CreateStreamingTask(int32 residency) override;
};