aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsarbes <sarbes@kodi.tv>2024-05-05 19:55:29 +0200
committerGitHub <noreply@github.com>2024-05-05 19:55:29 +0200
commitcaa22c102501cee860ceb8ee22c3955c579ae325 (patch)
treeeea45a3940212f8bf87ae0e4985cd0e013c371fb
parent222259a067633679d027bfa227f55d9879d2a290 (diff)
parent8c29d2ec8a84654cf5d38b428a7d4be98f2d2e91 (diff)
downloadxbmc-caa22c102501cee860ceb8ee22c3955c579ae325.tar.xz
Merge pull request #24508 from sarbes/texture-refactor
Refactoring Texture Handling
-rw-r--r--xbmc/guilib/CMakeLists.txt2
-rw-r--r--xbmc/guilib/Texture.cpp194
-rw-r--r--xbmc/guilib/Texture.h75
-rw-r--r--xbmc/guilib/TextureBase.cpp413
-rw-r--r--xbmc/guilib/TextureBase.h117
-rw-r--r--xbmc/guilib/TextureFormats.h155
6 files changed, 700 insertions, 256 deletions
diff --git a/xbmc/guilib/CMakeLists.txt b/xbmc/guilib/CMakeLists.txt
index 3e936cd9b9..a4c3957f55 100644
--- a/xbmc/guilib/CMakeLists.txt
+++ b/xbmc/guilib/CMakeLists.txt
@@ -66,6 +66,7 @@ set(SOURCES DDSImage.cpp
TextureBundle.cpp
TextureBundleXBT.cpp
Texture.cpp
+ TextureBase.cpp
TextureManager.cpp
VisibleEffect.cpp
XBTF.cpp
@@ -148,6 +149,7 @@ set(HEADERS DDSImage.h
LocalizeStrings.h
StereoscopicsManager.h
Texture.h
+ TextureBase.h
TextureBundle.h
TextureBundleXBT.h
TextureManager.h
diff --git a/xbmc/guilib/Texture.cpp b/xbmc/guilib/Texture.cpp
index cfc506d48c..af97003663 100644
--- a/xbmc/guilib/Texture.cpp
+++ b/xbmc/guilib/Texture.cpp
@@ -15,6 +15,7 @@
#include "filesystem/File.h"
#include "filesystem/ResourceFile.h"
#include "filesystem/XbtFile.h"
+#include "guilib/TextureBase.h"
#include "guilib/iimage.h"
#include "guilib/imagefactory.h"
#include "utils/URIUtils.h"
@@ -50,70 +51,6 @@ CTexture::~CTexture()
m_pixels = NULL;
}
-void CTexture::Allocate(unsigned int width, unsigned int height, XB_FMT format)
-{
- m_imageWidth = m_originalWidth = width;
- m_imageHeight = m_originalHeight = height;
- m_format = format;
- m_orientation = 0;
-
- m_textureWidth = m_imageWidth;
- m_textureHeight = m_imageHeight;
-
- if (m_format & XB_FMT_DXT_MASK)
- {
- while (GetPitch() < CServiceBroker::GetRenderSystem()->GetMinDXTPitch())
- m_textureWidth += GetBlockSize();
- }
-
- if (!CServiceBroker::GetRenderSystem()->SupportsNPOT((m_format & XB_FMT_DXT_MASK) != 0))
- {
- m_textureWidth = PadPow2(m_textureWidth);
- m_textureHeight = PadPow2(m_textureHeight);
- }
-
- if (m_format & XB_FMT_DXT_MASK)
- {
- // DXT textures must be a multiple of 4 in width and height
- m_textureWidth = ((m_textureWidth + 3) / 4) * 4;
- m_textureHeight = ((m_textureHeight + 3) / 4) * 4;
- }
- else
- {
- // align all textures so that they have an even width
- // in some circumstances when we downsize a thumbnail
- // which has an uneven number of pixels in width
- // we crash in CPicture::ScaleImage in ffmpegs swscale
- // because it tries to access beyond the source memory
- // (happens on osx and ios)
- // UPDATE: don't just update to be on an even width;
- // ffmpegs swscale relies on a 16-byte stride on some systems
- // so the textureWidth needs to be a multiple of 16. see ffmpeg
- // swscale headers for more info.
- m_textureWidth = ((m_textureWidth + 15) / 16) * 16;
- }
-
- // check for max texture size
- #define CLAMP(x, y) { if (x > y) x = y; }
- CLAMP(m_textureWidth, CServiceBroker::GetRenderSystem()->GetMaxTextureSize());
- CLAMP(m_textureHeight, CServiceBroker::GetRenderSystem()->GetMaxTextureSize());
- CLAMP(m_imageWidth, m_textureWidth);
- CLAMP(m_imageHeight, m_textureHeight);
-
- KODI::MEMORY::AlignedFree(m_pixels);
- m_pixels = NULL;
- if (GetPitch() * GetRows() > 0)
- {
- size_t size = GetPitch() * GetRows();
- m_pixels = static_cast<unsigned char*>(KODI::MEMORY::AlignedMalloc(size, 32));
-
- if (m_pixels == nullptr)
- {
- CLog::Log(LOGERROR, "{} - Could not allocate {} bytes. Out of memory.", __FUNCTION__, size);
- }
- }
-}
-
void CTexture::Update(unsigned int width,
unsigned int height,
unsigned int pitch,
@@ -156,39 +93,6 @@ void CTexture::Update(unsigned int width,
LoadToGPU();
}
-void CTexture::ClampToEdge()
-{
- if (m_pixels == nullptr)
- return;
-
- unsigned int imagePitch = GetPitch(m_imageWidth);
- unsigned int imageRows = GetRows(m_imageHeight);
- unsigned int texturePitch = GetPitch(m_textureWidth);
- unsigned int textureRows = GetRows(m_textureHeight);
- if (imagePitch < texturePitch)
- {
- unsigned int blockSize = GetBlockSize();
- unsigned char *src = m_pixels + imagePitch - blockSize;
- unsigned char *dst = m_pixels;
- for (unsigned int y = 0; y < imageRows; y++)
- {
- for (unsigned int x = imagePitch; x < texturePitch; x += blockSize)
- memcpy(dst + x, src, blockSize);
- dst += texturePitch;
- }
- }
-
- if (imageRows < textureRows)
- {
- unsigned char *dst = m_pixels + imageRows * texturePitch;
- for (unsigned int y = imageRows; y < textureRows; y++)
- {
- memcpy(dst, dst - texturePitch, texturePitch);
- dst += texturePitch;
- }
- }
-}
-
std::unique_ptr<CTexture> CTexture::LoadFromFile(const std::string& texturePath,
unsigned int idealWidth,
unsigned int idealHeight,
@@ -397,99 +301,3 @@ bool CTexture::LoadPaletted(unsigned int width,
ClampToEdge();
return true;
}
-
-unsigned int CTexture::PadPow2(unsigned int x)
-{
- --x;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- return ++x;
-}
-
-bool CTexture::SwapBlueRed(unsigned char* pixels,
- unsigned int height,
- unsigned int pitch,
- unsigned int elements,
- unsigned int offset)
-{
- if (!pixels) return false;
- unsigned char *dst = pixels;
- for (unsigned int y = 0; y < height; y++)
- {
- dst = pixels + (y * pitch);
- for (unsigned int x = 0; x < pitch; x+=elements)
- std::swap(dst[x+offset], dst[x+2+offset]);
- }
- return true;
-}
-
-unsigned int CTexture::GetPitch(unsigned int width) const
-{
- switch (m_format)
- {
- case XB_FMT_DXT1:
- return ((width + 3) / 4) * 8;
- case XB_FMT_DXT3:
- case XB_FMT_DXT5:
- case XB_FMT_DXT5_YCoCg:
- return ((width + 3) / 4) * 16;
- case XB_FMT_A8:
- return width;
- case XB_FMT_RGB8:
- return (((width + 1)* 3 / 4) * 4);
- case XB_FMT_RGBA8:
- case XB_FMT_A8R8G8B8:
- default:
- return width*4;
- }
-}
-
-unsigned int CTexture::GetRows(unsigned int height) const
-{
- switch (m_format)
- {
- case XB_FMT_DXT1:
- return (height + 3) / 4;
- case XB_FMT_DXT3:
- case XB_FMT_DXT5:
- case XB_FMT_DXT5_YCoCg:
- return (height + 3) / 4;
- default:
- return height;
- }
-}
-
-unsigned int CTexture::GetBlockSize() const
-{
- switch (m_format)
- {
- case XB_FMT_DXT1:
- return 8;
- case XB_FMT_DXT3:
- case XB_FMT_DXT5:
- case XB_FMT_DXT5_YCoCg:
- return 16;
- case XB_FMT_A8:
- return 1;
- default:
- return 4;
- }
-}
-
-bool CTexture::HasAlpha() const
-{
- return m_hasAlpha;
-}
-
-void CTexture::SetMipmapping()
-{
- m_mipmapping = true;
-}
-
-bool CTexture::IsMipmapped() const
-{
- return m_mipmapping;
-}
diff --git a/xbmc/guilib/Texture.h b/xbmc/guilib/Texture.h
index 5e32e60f8f..605d56b380 100644
--- a/xbmc/guilib/Texture.h
+++ b/xbmc/guilib/Texture.h
@@ -8,6 +8,7 @@
#pragma once
+#include "guilib/TextureBase.h"
#include "guilib/TextureFormats.h"
#include <cstddef>
@@ -21,17 +22,11 @@ class IImage;
struct COLOR {unsigned char b,g,r,x;}; // Windows GDI expects 4bytes per color
#pragma pack()
-enum class TEXTURE_SCALING
-{
- LINEAR,
- NEAREST,
-};
-
/*!
\ingroup textures
-\brief Base texture class, subclasses of which depend on the render spec (DX, GL etc.)
+\brief Texture loader class, subclasses of which depend on the render spec (DX, GL etc.)
*/
-class CTexture
+class CTexture : public CTextureBase
{
public:
@@ -86,47 +81,17 @@ public:
const unsigned char* pixels,
const COLOR* palette);
- bool HasAlpha() const;
- void SetAlpha(bool hasAlpha) { m_hasAlpha = hasAlpha; }
-
- void SetMipmapping();
- bool IsMipmapped() const;
- void SetScalingMethod(TEXTURE_SCALING scalingMethod) { m_scalingMethod = scalingMethod; }
- TEXTURE_SCALING GetScalingMethod() const { return m_scalingMethod; }
- void SetCacheMemory(bool bCacheMemory) { m_bCacheMemory = bCacheMemory; }
- bool GetCacheMemory() const { return m_bCacheMemory; }
-
- virtual void CreateTextureObject() = 0;
- virtual void DestroyTextureObject() = 0;
- virtual void LoadToGPU() = 0;
- virtual void BindToUnit(unsigned int unit) = 0;
-
- unsigned char* GetPixels() const { return m_pixels; }
- unsigned int GetPitch() const { return GetPitch(m_textureWidth); }
- unsigned int GetRows() const { return GetRows(m_textureHeight); }
- unsigned int GetTextureWidth() const { return m_textureWidth; }
- unsigned int GetTextureHeight() const { return m_textureHeight; }
- unsigned int GetWidth() const { return m_imageWidth; }
- unsigned int GetHeight() const { return m_imageHeight; }
- /*! \brief return the original width of the image, before scaling/cropping */
- unsigned int GetOriginalWidth() const { return m_originalWidth; }
- /*! \brief return the original height of the image, before scaling/cropping */
- unsigned int GetOriginalHeight() const { return m_originalHeight; }
-
- int GetOrientation() const { return m_orientation; }
- void SetOrientation(int orientation) { m_orientation = orientation; }
-
void Update(unsigned int width,
unsigned int height,
unsigned int pitch,
XB_FMT format,
const unsigned char* pixels,
bool loadToGPU);
- void Allocate(unsigned int width, unsigned int height, XB_FMT format);
- void ClampToEdge();
- static unsigned int PadPow2(unsigned int x);
- static bool SwapBlueRed(unsigned char *pixels, unsigned int height, unsigned int pitch, unsigned int elements = 4, unsigned int offset=0);
+ virtual void CreateTextureObject() = 0;
+ virtual void DestroyTextureObject() = 0;
+ virtual void LoadToGPU() = 0;
+ virtual void BindToUnit(unsigned int unit) = 0;
private:
// no copy constructor
@@ -136,25 +101,9 @@ protected:
bool LoadFromFileInMem(unsigned char* buffer, size_t size, const std::string& mimeType,
unsigned int maxWidth, unsigned int maxHeight);
bool LoadFromFileInternal(const std::string& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool requirePixels, const std::string& strMimeType = "");
- bool LoadIImage(IImage* pImage, unsigned char* buffer, unsigned int bufSize, unsigned int width, unsigned int height);
- // helpers for computation of texture parameters for compressed textures
- unsigned int GetPitch(unsigned int width) const;
- unsigned int GetRows(unsigned int height) const;
- unsigned int GetBlockSize() const;
-
- unsigned int m_imageWidth;
- unsigned int m_imageHeight;
- unsigned int m_textureWidth;
- unsigned int m_textureHeight;
- unsigned int m_originalWidth; ///< original image width before scaling or cropping
- unsigned int m_originalHeight; ///< original image height before scaling or cropping
-
- unsigned char* m_pixels;
- bool m_loadedToGPU;
- XB_FMT m_format;
- int m_orientation;
- bool m_hasAlpha = true ;
- bool m_mipmapping = false ;
- TEXTURE_SCALING m_scalingMethod = TEXTURE_SCALING::LINEAR;
- bool m_bCacheMemory = false;
+ bool LoadIImage(IImage* pImage,
+ unsigned char* buffer,
+ unsigned int bufSize,
+ unsigned int width,
+ unsigned int height);
};
diff --git a/xbmc/guilib/TextureBase.cpp b/xbmc/guilib/TextureBase.cpp
new file mode 100644
index 0000000000..5c2c01e22b
--- /dev/null
+++ b/xbmc/guilib/TextureBase.cpp
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "TextureBase.h"
+
+#include "ServiceBroker.h"
+#include "commons/ilog.h"
+#include "guilib/TextureFormats.h"
+#include "rendering/RenderSystem.h"
+#include "utils/MemUtils.h"
+#include "utils/log.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <exception>
+#include <utility>
+
+void CTextureBase::Allocate(uint32_t width, uint32_t height, XB_FMT format)
+{
+ SetKDFormat(format);
+ m_imageWidth = m_originalWidth = width;
+ m_imageHeight = m_originalHeight = height;
+ m_format = format;
+ m_orientation = 0;
+
+ m_textureWidth = m_imageWidth;
+ m_textureHeight = m_imageHeight;
+
+ if (!CServiceBroker::GetRenderSystem()->SupportsNPOT((m_textureFormat & KD_TEX_FMT_TYPE_MASK) !=
+ KD_TEX_FMT_S3TC))
+ {
+ m_textureWidth = PadPow2(m_textureWidth);
+ m_textureHeight = PadPow2(m_textureHeight);
+ }
+
+ if ((m_textureFormat & KD_TEX_FMT_TYPE_MASK) == KD_TEX_FMT_S3TC)
+ {
+ // DXT textures must be a multiple of 4 in width and height
+ m_textureWidth = ((m_textureWidth + 3) / 4) * 4;
+ m_textureHeight = ((m_textureHeight + 3) / 4) * 4;
+ }
+ else
+ {
+ // align all textures so that they have an even width
+ // in some circumstances when we downsize a thumbnail
+ // which has an uneven number of pixels in width
+ // we crash in CPicture::ScaleImage in ffmpegs swscale
+ // because it tries to access beyond the source memory
+ // (happens on osx and ios)
+ // UPDATE: don't just update to be on an even width;
+ // ffmpegs swscale relies on a 16-byte stride on some systems
+ // so the textureWidth needs to be a multiple of 16. see ffmpeg
+ // swscale headers for more info.
+ m_textureWidth = ((m_textureWidth + 15) / 16) * 16;
+ }
+
+ // check for max texture size
+ m_textureWidth = std::min(m_textureWidth, CServiceBroker::GetRenderSystem()->GetMaxTextureSize());
+ m_textureHeight =
+ std::min(m_textureHeight, CServiceBroker::GetRenderSystem()->GetMaxTextureSize());
+ m_imageWidth = std::min(m_imageWidth, m_textureWidth);
+ m_imageHeight = std::min(m_imageHeight, m_textureHeight);
+
+ KODI::MEMORY::AlignedFree(m_pixels);
+ m_pixels = NULL;
+
+ size_t size = GetPitch() * GetRows();
+
+ if (size == 0)
+ return;
+
+ m_pixels = static_cast<unsigned char*>(KODI::MEMORY::AlignedMalloc(size, 32));
+
+ if (m_pixels == nullptr)
+ CLog::Log(LOGERROR, "{} - Could not allocate {} bytes. Out of memory.", __FUNCTION__, size);
+}
+
+uint32_t CTextureBase::PadPow2(uint32_t x)
+{
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return ++x;
+}
+
+bool CTextureBase::SwapBlueRed(
+ uint8_t* pixels, uint32_t height, uint32_t pitch, uint32_t elements, uint32_t offset)
+{
+ if (!pixels)
+ return false;
+ uint8_t* dst = pixels;
+ for (uint32_t y = 0; y < height; y++)
+ {
+ dst = pixels + (y * pitch);
+ for (uint32_t x = 0; x < pitch; x += elements)
+ std::swap(dst[x + offset], dst[x + 2 + offset]);
+ }
+ return true;
+}
+
+void CTextureBase::ClampToEdge()
+{
+ if (m_pixels == nullptr)
+ return;
+
+ uint32_t imagePitch = GetPitch(m_imageWidth);
+ uint32_t imageRows = GetRows(m_imageHeight);
+ uint32_t texturePitch = GetPitch(m_textureWidth);
+ uint32_t textureRows = GetRows(m_textureHeight);
+
+ if (imagePitch < texturePitch)
+ {
+ uint32_t blockSize = GetBlockSize();
+ unsigned char* src = m_pixels + imagePitch - blockSize;
+ unsigned char* dst = m_pixels;
+ for (uint32_t y = 0; y < imageRows; y++)
+ {
+ for (uint32_t x = imagePitch; x < texturePitch; x += blockSize)
+ memcpy(dst + x, src, blockSize);
+ dst += texturePitch;
+ }
+ }
+
+ if (imageRows < textureRows)
+ {
+ unsigned char* dst = m_pixels + imageRows * texturePitch;
+ for (uint32_t y = imageRows; y < textureRows; y++)
+ {
+ memcpy(dst, dst - texturePitch, texturePitch);
+ dst += texturePitch;
+ }
+ }
+}
+
+uint32_t CTextureBase::GetPitch(uint32_t width) const
+{
+ uint32_t blockWidth = GetBlockWidth();
+ uint32_t pitch = ((width + blockWidth - 1) / blockWidth) * GetBlockSize();
+
+ // For the GPU, RGB8 needs to be aligned to 32 bit
+ if (m_textureFormat == KD_TEX_FMT_SDR_RGB8)
+ pitch = ((pitch + 3) / 4) * 4;
+
+ return pitch;
+}
+
+uint32_t CTextureBase::GetRows(uint32_t height) const
+{
+ uint32_t blockHeight = GetBlockHeight();
+ return (height + blockHeight - 1) / blockHeight;
+}
+
+uint32_t CTextureBase::GetBlockWidth() const
+{
+ switch (m_textureFormat)
+ {
+ case KD_TEX_FMT_SDR_R8:
+ case KD_TEX_FMT_SDR_RG8:
+ case KD_TEX_FMT_SDR_R5G6B5:
+ case KD_TEX_FMT_SDR_RGB5_A1:
+ case KD_TEX_FMT_SDR_RGBA4:
+ case KD_TEX_FMT_SDR_RGB8:
+ case KD_TEX_FMT_SDR_RGBA8:
+ case KD_TEX_FMT_SDR_BGRA8:
+ case KD_TEX_FMT_HDR_R16f:
+ case KD_TEX_FMT_HDR_RG16f:
+ case KD_TEX_FMT_HDR_R11F_G11F_B10F:
+ case KD_TEX_FMT_HDR_RGB9_E5:
+ case KD_TEX_FMT_HDR_RGB10_A2:
+ case KD_TEX_FMT_HDR_RGBA16f:
+ return 1;
+ case KD_TEX_FMT_YUV_YUYV8:
+ return 2;
+ case KD_TEX_FMT_S3TC_RGB8:
+ case KD_TEX_FMT_S3TC_RGB8_A1:
+ case KD_TEX_FMT_S3TC_RGB8_A4:
+ case KD_TEX_FMT_S3TC_RGBA8:
+ case KD_TEX_FMT_RGTC_R11:
+ case KD_TEX_FMT_RGTC_RG11:
+ case KD_TEX_FMT_BPTC_RGB16F:
+ case KD_TEX_FMT_BPTC_RGBA8:
+ case KD_TEX_FMT_ETC1:
+ case KD_TEX_FMT_ETC2_RGB8:
+ case KD_TEX_FMT_ETC2_RGB8_A1:
+ case KD_TEX_FMT_ETC2_RGBA8:
+ case KD_TEX_FMT_ETC2_R11:
+ case KD_TEX_FMT_ETC2_RG11:
+ case KD_TEX_FMT_ASTC_LDR_4x4:
+ case KD_TEX_FMT_ASTC_HDR_4x4:
+ return 4;
+ case KD_TEX_FMT_ASTC_LDR_5x4:
+ case KD_TEX_FMT_ASTC_LDR_5x5:
+ case KD_TEX_FMT_ASTC_HDR_5x4:
+ case KD_TEX_FMT_ASTC_HDR_5x5:
+ return 5;
+ case KD_TEX_FMT_ASTC_LDR_6x5:
+ case KD_TEX_FMT_ASTC_LDR_6x6:
+ case KD_TEX_FMT_ASTC_HDR_6x5:
+ case KD_TEX_FMT_ASTC_HDR_6x6:
+ return 6;
+ case KD_TEX_FMT_ASTC_LDR_8x5:
+ case KD_TEX_FMT_ASTC_LDR_8x6:
+ case KD_TEX_FMT_ASTC_LDR_8x8:
+ case KD_TEX_FMT_ASTC_HDR_8x5:
+ case KD_TEX_FMT_ASTC_HDR_8x6:
+ case KD_TEX_FMT_ASTC_HDR_8x8:
+ return 8;
+ case KD_TEX_FMT_ASTC_LDR_10x5:
+ case KD_TEX_FMT_ASTC_LDR_10x6:
+ case KD_TEX_FMT_ASTC_LDR_10x8:
+ case KD_TEX_FMT_ASTC_LDR_10x10:
+ case KD_TEX_FMT_ASTC_HDR_10x5:
+ case KD_TEX_FMT_ASTC_HDR_10x6:
+ case KD_TEX_FMT_ASTC_HDR_10x8:
+ case KD_TEX_FMT_ASTC_HDR_10x10:
+ return 10;
+ case KD_TEX_FMT_ASTC_LDR_12x10:
+ case KD_TEX_FMT_ASTC_LDR_12x12:
+ case KD_TEX_FMT_ASTC_HDR_12x10:
+ case KD_TEX_FMT_ASTC_HDR_12x12:
+ return 12;
+ default:
+ return 1;
+ }
+}
+
+uint32_t CTextureBase::GetBlockHeight() const
+{
+ switch (m_textureFormat)
+ {
+ case KD_TEX_FMT_SDR_R8:
+ case KD_TEX_FMT_SDR_RG8:
+ case KD_TEX_FMT_SDR_R5G6B5:
+ case KD_TEX_FMT_SDR_RGB5_A1:
+ case KD_TEX_FMT_SDR_RGBA4:
+ case KD_TEX_FMT_SDR_RGB8:
+ case KD_TEX_FMT_SDR_RGBA8:
+ case KD_TEX_FMT_SDR_BGRA8:
+ case KD_TEX_FMT_HDR_R16f:
+ case KD_TEX_FMT_HDR_RG16f:
+ case KD_TEX_FMT_HDR_R11F_G11F_B10F:
+ case KD_TEX_FMT_HDR_RGB9_E5:
+ case KD_TEX_FMT_HDR_RGB10_A2:
+ case KD_TEX_FMT_HDR_RGBA16f:
+ case KD_TEX_FMT_YUV_YUYV8:
+ return 1;
+ case KD_TEX_FMT_S3TC_RGB8:
+ case KD_TEX_FMT_S3TC_RGB8_A1:
+ case KD_TEX_FMT_S3TC_RGB8_A4:
+ case KD_TEX_FMT_S3TC_RGBA8:
+ case KD_TEX_FMT_RGTC_R11:
+ case KD_TEX_FMT_RGTC_RG11:
+ case KD_TEX_FMT_BPTC_RGB16F:
+ case KD_TEX_FMT_BPTC_RGBA8:
+ case KD_TEX_FMT_ETC1:
+ case KD_TEX_FMT_ETC2_RGB8:
+ case KD_TEX_FMT_ETC2_RGB8_A1:
+ case KD_TEX_FMT_ETC2_RGBA8:
+ case KD_TEX_FMT_ETC2_R11:
+ case KD_TEX_FMT_ETC2_RG11:
+ case KD_TEX_FMT_ASTC_LDR_4x4:
+ case KD_TEX_FMT_ASTC_LDR_5x4:
+ case KD_TEX_FMT_ASTC_HDR_4x4:
+ case KD_TEX_FMT_ASTC_HDR_5x4:
+ return 4;
+ case KD_TEX_FMT_ASTC_LDR_5x5:
+ case KD_TEX_FMT_ASTC_LDR_6x5:
+ case KD_TEX_FMT_ASTC_LDR_8x5:
+ case KD_TEX_FMT_ASTC_LDR_10x5:
+ case KD_TEX_FMT_ASTC_HDR_5x5:
+ case KD_TEX_FMT_ASTC_HDR_6x5:
+ case KD_TEX_FMT_ASTC_HDR_8x5:
+ case KD_TEX_FMT_ASTC_HDR_10x5:
+ return 5;
+ case KD_TEX_FMT_ASTC_LDR_6x6:
+ case KD_TEX_FMT_ASTC_LDR_8x6:
+ case KD_TEX_FMT_ASTC_LDR_10x6:
+ case KD_TEX_FMT_ASTC_HDR_6x6:
+ case KD_TEX_FMT_ASTC_HDR_8x6:
+ case KD_TEX_FMT_ASTC_HDR_10x6:
+ return 6;
+ case KD_TEX_FMT_ASTC_LDR_8x8:
+ case KD_TEX_FMT_ASTC_LDR_10x8:
+ case KD_TEX_FMT_ASTC_HDR_8x8:
+ case KD_TEX_FMT_ASTC_HDR_10x8:
+ return 8;
+ case KD_TEX_FMT_ASTC_LDR_10x10:
+ case KD_TEX_FMT_ASTC_LDR_12x10:
+ case KD_TEX_FMT_ASTC_HDR_10x10:
+ case KD_TEX_FMT_ASTC_HDR_12x10:
+ return 10;
+ case KD_TEX_FMT_ASTC_LDR_12x12:
+ case KD_TEX_FMT_ASTC_HDR_12x12:
+ return 12;
+ default:
+ return 4;
+ }
+}
+
+uint32_t CTextureBase::GetBlockSize() const
+{
+ switch (m_textureFormat)
+ {
+ case KD_TEX_FMT_SDR_R8:
+ return 1;
+ case KD_TEX_FMT_SDR_RG8:
+ case KD_TEX_FMT_SDR_R5G6B5:
+ case KD_TEX_FMT_SDR_RGB5_A1:
+ case KD_TEX_FMT_SDR_RGBA4:
+ case KD_TEX_FMT_HDR_R16f:
+ return 2;
+ case KD_TEX_FMT_SDR_RGB8:
+ return 3;
+ case KD_TEX_FMT_SDR_RGBA8:
+ case KD_TEX_FMT_SDR_BGRA8:
+ case KD_TEX_FMT_HDR_RG16f:
+ case KD_TEX_FMT_HDR_R11F_G11F_B10F:
+ case KD_TEX_FMT_HDR_RGB9_E5:
+ case KD_TEX_FMT_HDR_RGB10_A2:
+ case KD_TEX_FMT_YUV_YUYV8:
+ return 4;
+ case KD_TEX_FMT_HDR_RGBA16f:
+ case KD_TEX_FMT_S3TC_RGB8:
+ case KD_TEX_FMT_S3TC_RGB8_A1:
+ case KD_TEX_FMT_RGTC_R11:
+ case KD_TEX_FMT_ETC1:
+ case KD_TEX_FMT_ETC2_RGB8:
+ case KD_TEX_FMT_ETC2_RGB8_A1:
+ case KD_TEX_FMT_ETC2_R11:
+ return 8;
+ case KD_TEX_FMT_S3TC_RGB8_A4:
+ case KD_TEX_FMT_S3TC_RGBA8:
+ case KD_TEX_FMT_RGTC_RG11:
+ case KD_TEX_FMT_BPTC_RGB16F:
+ case KD_TEX_FMT_BPTC_RGBA8:
+ case KD_TEX_FMT_ETC2_RG11:
+ case KD_TEX_FMT_ETC2_RGBA8:
+ case KD_TEX_FMT_ASTC_LDR_4x4:
+ case KD_TEX_FMT_ASTC_LDR_5x4:
+ case KD_TEX_FMT_ASTC_LDR_5x5:
+ case KD_TEX_FMT_ASTC_LDR_6x5:
+ case KD_TEX_FMT_ASTC_LDR_6x6:
+ case KD_TEX_FMT_ASTC_LDR_8x5:
+ case KD_TEX_FMT_ASTC_LDR_8x6:
+ case KD_TEX_FMT_ASTC_LDR_8x8:
+ case KD_TEX_FMT_ASTC_LDR_10x5:
+ case KD_TEX_FMT_ASTC_LDR_10x6:
+ case KD_TEX_FMT_ASTC_LDR_10x8:
+ case KD_TEX_FMT_ASTC_LDR_10x10:
+ case KD_TEX_FMT_ASTC_LDR_12x10:
+ case KD_TEX_FMT_ASTC_LDR_12x12:
+ case KD_TEX_FMT_ASTC_HDR_4x4:
+ case KD_TEX_FMT_ASTC_HDR_5x4:
+ case KD_TEX_FMT_ASTC_HDR_5x5:
+ case KD_TEX_FMT_ASTC_HDR_6x5:
+ case KD_TEX_FMT_ASTC_HDR_6x6:
+ case KD_TEX_FMT_ASTC_HDR_8x5:
+ case KD_TEX_FMT_ASTC_HDR_8x6:
+ case KD_TEX_FMT_ASTC_HDR_8x8:
+ case KD_TEX_FMT_ASTC_HDR_10x5:
+ case KD_TEX_FMT_ASTC_HDR_10x6:
+ case KD_TEX_FMT_ASTC_HDR_10x8:
+ case KD_TEX_FMT_ASTC_HDR_10x10:
+ case KD_TEX_FMT_ASTC_HDR_12x10:
+ case KD_TEX_FMT_ASTC_HDR_12x12:
+ return 16;
+ default:
+ return 4;
+ }
+}
+
+void CTextureBase::SetKDFormat(XB_FMT xbFMT)
+{
+ switch (xbFMT)
+ {
+ case XB_FMT_DXT1:
+ m_textureFormat = KD_TEX_FMT_S3TC_RGB8;
+ return;
+ case XB_FMT_DXT3:
+ m_textureFormat = KD_TEX_FMT_S3TC_RGB8_A4;
+ return;
+ case XB_FMT_DXT5:
+ m_textureFormat = KD_TEX_FMT_S3TC_RGBA8;
+ return;
+ case XB_FMT_A8R8G8B8:
+ m_textureFormat = KD_TEX_FMT_SDR_BGRA8;
+ return;
+ case XB_FMT_A8:
+ m_textureFormat = KD_TEX_FMT_SDR_R8;
+ m_textureSwizzle = KD_TEX_SWIZ_111R;
+ return;
+ case XB_FMT_RGBA8:
+ m_textureFormat = KD_TEX_FMT_SDR_RGBA8;
+ return;
+ case XB_FMT_RGB8:
+ m_textureFormat = KD_TEX_FMT_SDR_RGB8;
+ return;
+ case XB_FMT_UNKNOWN:
+ case XB_FMT_DXT5_YCoCg:
+ default:
+ m_textureFormat = KD_TEX_FMT_UNKNOWN;
+ return;
+ }
+}
diff --git a/xbmc/guilib/TextureBase.h b/xbmc/guilib/TextureBase.h
new file mode 100644
index 0000000000..bbabe2ae46
--- /dev/null
+++ b/xbmc/guilib/TextureBase.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "guilib/TextureFormats.h"
+
+#include <memory>
+#include <string>
+
+enum class TEXTURE_SCALING
+{
+ LINEAR,
+ NEAREST,
+};
+
+/*!
+\ingroup textures
+\brief Base texture class, which holds the state of the texture, as well as all conversion functions.
+*/
+class CTextureBase
+{
+
+public:
+ CTextureBase() = default;
+ ~CTextureBase() = default;
+
+ bool HasAlpha() const { return m_hasAlpha; }
+ void SetAlpha(bool hasAlpha) { m_hasAlpha = hasAlpha; }
+
+ /*! \brief sets mipmapping. do not use in new code. will be replaced with proper scaling. */
+ void SetMipmapping() { m_mipmapping = true; }
+ /*! \brief return true if we want to mipmap */
+ bool IsMipmapped() const { return m_mipmapping; }
+
+ /*! \brief sets the scaling method. scanout systems might support more than NN/linear. */
+ void SetScalingMethod(TEXTURE_SCALING scalingMethod) { m_scalingMethod = scalingMethod; }
+ /*! \brief returns the scaling method. */
+ TEXTURE_SCALING GetScalingMethod() const { return m_scalingMethod; }
+
+ int32_t GetOrientation() const { return m_orientation; }
+ void SetOrientation(int orientation) { m_orientation = orientation; }
+
+ /*! \brief retains a shadow copy of the texture on the CPU side. */
+ void SetCacheMemory(bool bCacheMemory) { m_bCacheMemory = bCacheMemory; }
+ /*! \brief returns true if a shadow copy is kept on the CPU side. */
+ bool GetCacheMemory() const { return m_bCacheMemory; }
+
+ /*! \brief returns a pointer to the staging texture. */
+ uint8_t* GetPixels() const { return m_pixels; }
+
+ /*! \brief return the size of one row in bytes. */
+ uint32_t GetPitch() const { return GetPitch(m_textureWidth); }
+ /*! \brief return the number of rows (number of blocks in the Y direction). */
+ uint32_t GetRows() const { return GetRows(m_textureHeight); }
+ /*! \brief return the total width of the texture, which might be scaled to fit its displayed size. */
+ uint32_t GetTextureWidth() const { return m_textureWidth; }
+ /*! \brief return the total height of the texture, which might be scaled to fit its displayed size. */
+ uint32_t GetTextureHeight() const { return m_textureHeight; }
+ /*! \brief return the total width of "active" area, which might be equal or lower than the texture width due to alignment. */
+ uint32_t GetWidth() const { return m_imageWidth; }
+ /*! \brief return the total height of "active" area, which might be equal or lower than the texture height due to alignment. */
+ uint32_t GetHeight() const { return m_imageHeight; }
+ /*! \brief return the original width of the image, before scaling/cropping */
+ uint32_t GetOriginalWidth() const { return m_originalWidth; }
+ /*! \brief return the original height of the image, before scaling/cropping */
+ uint32_t GetOriginalHeight() const { return m_originalHeight; }
+
+ // allocates staging texture space.
+ void Allocate(uint32_t width, uint32_t height, XB_FMT format);
+ void ClampToEdge();
+
+ /*! \brief rounds to power of two. deprecated. */
+ static uint32_t PadPow2(uint32_t x);
+ /*! \brief swaps the blue/red channel. deprecated in this form. */
+ static bool SwapBlueRed(
+ uint8_t* pixels, uint32_t height, uint32_t pitch, uint32_t elements = 4, uint32_t offset = 0);
+
+protected:
+ // helpers for computation of texture parameters for compressed textures
+ uint32_t GetPitch(uint32_t width) const;
+ uint32_t GetRows(uint32_t height) const;
+ uint32_t GetBlockWidth() const;
+ uint32_t GetBlockHeight() const;
+ /*! \brief return the size of a compression block (tile) in bytes. */
+ uint32_t GetBlockSize() const;
+
+ void SetKDFormat(XB_FMT xbFMT);
+
+ uint32_t m_imageWidth{0};
+ uint32_t m_imageHeight{0};
+ uint32_t m_textureWidth{0};
+ uint32_t m_textureHeight{0};
+ uint32_t m_originalWidth{0}; ///< original image width before scaling or cropping
+ uint32_t m_originalHeight{0}; ///< original image height before scaling or cropping
+
+ uint8_t* m_pixels{nullptr};
+ bool m_loadedToGPU{false};
+
+ KD_TEX_FMT m_textureFormat{KD_TEX_FMT_UNKNOWN}; // new Kodi texture format
+ KD_TEX_SWIZ m_textureSwizzle{KD_TEX_SWIZ_RGBA};
+ KD_TEX_COL m_textureColorspace{KD_TEX_COL_REC709};
+ KD_TEX_TRANSFER m_textureTransfer{KD_TEX_TRANSFER_SRGB};
+ KD_TEX_ALPHA m_textureAlpha{KD_TEX_ALPHA_STRAIGHT};
+
+ XB_FMT m_format{XB_FMT_UNKNOWN}; // legacy XB format, deprecated
+ int32_t m_orientation{0};
+ bool m_hasAlpha{true};
+ bool m_mipmapping{false};
+ TEXTURE_SCALING m_scalingMethod{TEXTURE_SCALING::LINEAR};
+ bool m_bCacheMemory{false};
+};
diff --git a/xbmc/guilib/TextureFormats.h b/xbmc/guilib/TextureFormats.h
index 2aab71a947..5b7d87c5fb 100644
--- a/xbmc/guilib/TextureFormats.h
+++ b/xbmc/guilib/TextureFormats.h
@@ -25,4 +25,159 @@ enum XB_FMT
XB_FMT_MASK = 0xFFFF,
XB_FMT_OPAQUE = 0x10000,
};
+
+enum KD_TEX_FMT
+{
+ KD_TEX_FMT_UNKNOWN = 0x0000,
+
+ // Legacy XB_FMT formats family
+ KD_TEX_FMT_LEGACY = 0x0000,
+
+ // SDR texture family
+ KD_TEX_FMT_SDR = 0x1000,
+ KD_TEX_FMT_SDR_R8 = 0x1000, // 8bpp, single channel
+ KD_TEX_FMT_SDR_RG8 = 0x1100, // 16bpp, dual channel
+ KD_TEX_FMT_SDR_R5G6B5 = 0x1200, // 16bpp, 5/6 bit per color channel
+ KD_TEX_FMT_SDR_RGB5_A1 = 0x1300, // 16bpp, 5 bit per color channel, pt-alpha
+ KD_TEX_FMT_SDR_RGBA4 = 0x1400, // 16bpp, 4 bit per channel
+ KD_TEX_FMT_SDR_RGB8 = 0x1500, // 24bpp, 8 bit per channel, no alpha (unsuitable for GPUs!)
+ KD_TEX_FMT_SDR_RGBA8 = 0x1600, // 32bpp, 8 bit per channel, RGBA order
+ KD_TEX_FMT_SDR_BGRA8 = 0x1700, // 32bpp, 8 bit per channel, BGRA order
+
+ // HDR texture family
+ KD_TEX_FMT_HDR = 0x2000,
+ KD_TEX_FMT_HDR_R16f = 0x2100, // 16bpp, single channel float
+ KD_TEX_FMT_HDR_RG16f = 0x2200, // 32bpp, dual channel float
+ KD_TEX_FMT_HDR_R11F_G11F_B10F = 0x2300, // 32bpp, 6e5/5e5 per color channel
+ KD_TEX_FMT_HDR_RGB9_E5 = 0x2400, // 32bpp, 9 bit color, shared 5 bit exponent
+ KD_TEX_FMT_HDR_RGB10_A2 = 0x2500, // 32bpp, 10 bit color, 2 bit alpha
+ KD_TEX_FMT_HDR_RGBA16f = 0x2600, // 64bpp, four channel float
+
+ // YUV texture family
+ KD_TEX_FMT_YUV = 0x3000,
+ KD_TEX_FMT_YUV_YUYV8 = 0x3000, // 16bpp, 4:2:2 packed
+
+ // S3TC texture family
+ KD_TEX_FMT_S3TC = 0x4000,
+ KD_TEX_FMT_S3TC_RGB8 = 0x4000, // 4bpp, RGB (BC1)
+ KD_TEX_FMT_S3TC_RGB8_A1 = 0x4100, // 4bpp, RGB, pt-alpha (BC1)
+ KD_TEX_FMT_S3TC_RGB8_A4 = 0x4200, // 8bpp, RGB, 4 bit alpha (BC2)
+ KD_TEX_FMT_S3TC_RGBA8 = 0x4300, // 8bpp, RGBA (BC3)
+
+ // RGTC (LATC) texture family
+ KD_TEX_FMT_RGTC = 0x5000,
+ KD_TEX_FMT_RGTC_R11 = 0x5000, // 4bpp, single channel (BC4)
+ KD_TEX_FMT_RGTC_RG11 = 0x5100, // 8bpp, dual channel (BC5)
+
+ // BPTC texture family
+ KD_TEX_FMT_BPTC = 0x6000,
+ KD_TEX_FMT_BPTC_RGB16F = 0x6000, // 8bpp, HDR (BC6H float)
+ KD_TEX_FMT_BPTC_RGBA8 = 0x6100, // 8bpp, LDR (BC7 unorm)
+
+ // ETC1 texture family
+ KD_TEX_FMT_ETC1 = 0x7000,
+ KD_TEX_FMT_ETC1_RGB8 = 0x7000, // 4bpp, RGB
+
+ // ETC2 texture family
+ KD_TEX_FMT_ETC2 = 0x8000,
+ KD_TEX_FMT_ETC2_R11 = 0x8100, // 4bpp, single channel (EAC)
+ KD_TEX_FMT_ETC2_RG11 = 0x8200, // 8bpp, dual channel (EAC)
+ KD_TEX_FMT_ETC2_RGB8 = 0x8300, // 4bpp, RGB
+ KD_TEX_FMT_ETC2_RGB8_A1 = 0x8400, // 4bpp, RGB, pt-alpha
+ KD_TEX_FMT_ETC2_RGBA8 = 0x8500, // 8bpp, RGB, alpha EAC
+
+ // ASTC LDR texture family
+ // Bitrate varies from 8bpp (4x4 tile) to 0.89bpp (12x12 tile).
+ KD_TEX_FMT_ASTC_LDR = 0x9000,
+ KD_TEX_FMT_ASTC_LDR_4x4 = 0x9000,
+ KD_TEX_FMT_ASTC_LDR_5x4 = 0x9100,
+ KD_TEX_FMT_ASTC_LDR_5x5 = 0x9200,
+ KD_TEX_FMT_ASTC_LDR_6x5 = 0x9300,
+ KD_TEX_FMT_ASTC_LDR_6x6 = 0x9400,
+ KD_TEX_FMT_ASTC_LDR_8x5 = 0x9500,
+ KD_TEX_FMT_ASTC_LDR_8x6 = 0x9600,
+ KD_TEX_FMT_ASTC_LDR_8x8 = 0x9700,
+ KD_TEX_FMT_ASTC_LDR_10x5 = 0x9800,
+ KD_TEX_FMT_ASTC_LDR_10x6 = 0x9900,
+ KD_TEX_FMT_ASTC_LDR_10x8 = 0x9A00,
+ KD_TEX_FMT_ASTC_LDR_10x10 = 0x9B00,
+ KD_TEX_FMT_ASTC_LDR_12x10 = 0x9C00,
+ KD_TEX_FMT_ASTC_LDR_12x12 = 0x9D00,
+
+ // ASTC HDR texture family
+ // Bitrate varies from 8bpp (4x4 tile) to 0.89bpp (12x12 tile).
+ KD_TEX_FMT_ASTC_HDR = 0xA000,
+ KD_TEX_FMT_ASTC_HDR_4x4 = 0xA000,
+ KD_TEX_FMT_ASTC_HDR_5x4 = 0xA100,
+ KD_TEX_FMT_ASTC_HDR_5x5 = 0xA200,
+ KD_TEX_FMT_ASTC_HDR_6x5 = 0xA300,
+ KD_TEX_FMT_ASTC_HDR_6x6 = 0xA400,
+ KD_TEX_FMT_ASTC_HDR_8x5 = 0xA500,
+ KD_TEX_FMT_ASTC_HDR_8x6 = 0xA600,
+ KD_TEX_FMT_ASTC_HDR_8x8 = 0xA700,
+ KD_TEX_FMT_ASTC_HDR_10x5 = 0xA800,
+ KD_TEX_FMT_ASTC_HDR_10x6 = 0xA900,
+ KD_TEX_FMT_ASTC_HDR_10x8 = 0xAA00,
+ KD_TEX_FMT_ASTC_HDR_10x10 = 0xAB00,
+ KD_TEX_FMT_ASTC_HDR_12x10 = 0xAC00,
+ KD_TEX_FMT_ASTC_HDR_12x12 = 0xAD00,
+
+ KD_TEX_FMT_TYPE_MASK = 0xF000,
+
+ KD_TEX_FMT_MASK = 0xFFFF,
+};
+
+// Alpha handling
+enum KD_TEX_ALPHA
+{
+ KD_TEX_ALPHA_STRAIGHT = 0x00000, // Straight (unmultiplied) alpha
+ KD_TEX_ALPHA_OPAQUE = 0x10000, // No alpha
+ KD_TEX_ALPHA_PREMULTIPLIED = 0x20000, // Premultiplied alpha
+
+ KD_TEX_ALPHA_MASK = 0xF0000,
+};
+
+// Texture component swizzle or effect
+enum KD_TEX_SWIZ
+{
+ KD_TEX_SWIZ_RGBA = 0x000000, // No swizzling
+ KD_TEX_SWIZ_RGB1 = 0x100000, // Normal swizzle, ignoring alpha
+ KD_TEX_SWIZ_RRR1 = 0x200000, // Luminance
+ KD_TEX_SWIZ_111R = 0x300000, // Alpha
+ KD_TEX_SWIZ_RRRG = 0x400000, // Luminance-Alpha
+ KD_TEX_SWIZ_RRRR = 0x500000, // Intensity
+ KD_TEX_SWIZ_GGG1 = 0x600000, // Luminance (ETC1/BC1)
+ KD_TEX_SWIZ_111G = 0x700000, // Alpha (ETC1/BC1)
+ KD_TEX_SWIZ_GGGA = 0x800000, // Luminance-Alpha (BC2/BC3)
+ KD_TEX_SWIZ_GGGG = 0x900000, // Intensity (ETC1/BC1)
+
+ KD_TEX_SWIZ_SDF = 0xa00000, // Red channel contains a SDF
+ KD_TEX_SWIZ_RGB_SDF = 0xb00000, // RGB8 texture with a SDF packed in the alpha channel
+ KD_TEX_SWIZ_MSDF = 0xc00000, // Encoded MSDF in the color channels, Alpha is ignored
+
+ KD_TEX_SWIZ_MASK = 0xF00000,
+};
+
+// Color space
+enum KD_TEX_COL
+{
+ KD_TEX_COL_REC709 = 0x0000000, // REC709/sRGB color space
+ KD_TEX_COL_REC2020 = 0x1000000, // REC2020 color space
+
+ KD_TEX_COL_MASK = 0xF000000,
+};
+
+// Transfer function
+enum KD_TEX_TRANSFER
+{
+ KD_TEX_TRANSFER_SRGB = 0x00000000,
+ KD_TEX_TRANSFER_REC709 = 0x10000000,
+ KD_TEX_TRANSFER_HLG = 0x20000000,
+ KD_TEX_TRANSFER_LINEAR = 0x30000000,
+ KD_TEX_TRANSFER_SQUARED = 0x40000000,
+ KD_TEX_TRANSFER_PQ = 0x50000000,
+
+ KD_TEX_TRANSFER_MASK = 0xF0000000,
+};
+
// clang-format on