2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "TextureBase.h"
11 #include "ServiceBroker.h"
12 #include "commons/ilog.h"
13 #include "guilib/TextureFormats.h"
14 #include "rendering/RenderSystem.h"
15 #include "utils/MemUtils.h"
16 #include "utils/log.h"
24 void CTextureBase::Allocate(uint32_t width
, uint32_t height
, XB_FMT format
)
27 m_imageWidth
= m_originalWidth
= width
;
28 m_imageHeight
= m_originalHeight
= height
;
32 m_textureWidth
= m_imageWidth
;
33 m_textureHeight
= m_imageHeight
;
35 if (!CServiceBroker::GetRenderSystem()->SupportsNPOT((m_textureFormat
& KD_TEX_FMT_TYPE_MASK
) !=
38 m_textureWidth
= PadPow2(m_textureWidth
);
39 m_textureHeight
= PadPow2(m_textureHeight
);
42 if ((m_textureFormat
& KD_TEX_FMT_TYPE_MASK
) == KD_TEX_FMT_S3TC
)
44 // DXT textures must be a multiple of 4 in width and height
45 m_textureWidth
= ((m_textureWidth
+ 3) / 4) * 4;
46 m_textureHeight
= ((m_textureHeight
+ 3) / 4) * 4;
50 // align all textures so that they have an even width
51 // in some circumstances when we downsize a thumbnail
52 // which has an uneven number of pixels in width
53 // we crash in CPicture::ScaleImage in ffmpegs swscale
54 // because it tries to access beyond the source memory
55 // (happens on osx and ios)
56 // UPDATE: don't just update to be on an even width;
57 // ffmpegs swscale relies on a 16-byte stride on some systems
58 // so the textureWidth needs to be a multiple of 16. see ffmpeg
59 // swscale headers for more info.
60 m_textureWidth
= ((m_textureWidth
+ 15) / 16) * 16;
63 // check for max texture size
64 m_textureWidth
= std::min(m_textureWidth
, CServiceBroker::GetRenderSystem()->GetMaxTextureSize());
66 std::min(m_textureHeight
, CServiceBroker::GetRenderSystem()->GetMaxTextureSize());
67 m_imageWidth
= std::min(m_imageWidth
, m_textureWidth
);
68 m_imageHeight
= std::min(m_imageHeight
, m_textureHeight
);
70 KODI::MEMORY::AlignedFree(m_pixels
);
73 size_t size
= GetPitch() * GetRows();
78 m_pixels
= static_cast<unsigned char*>(KODI::MEMORY::AlignedMalloc(size
, 32));
80 if (m_pixels
== nullptr)
81 CLog::Log(LOGERROR
, "{} - Could not allocate {} bytes. Out of memory.", __FUNCTION__
, size
);
84 uint32_t CTextureBase::PadPow2(uint32_t x
)
95 bool CTextureBase::SwapBlueRed(
96 uint8_t* pixels
, uint32_t height
, uint32_t pitch
, uint32_t elements
, uint32_t offset
)
100 uint8_t* dst
= pixels
;
101 for (uint32_t y
= 0; y
< height
; y
++)
103 dst
= pixels
+ (y
* pitch
);
104 for (uint32_t x
= 0; x
< pitch
; x
+= elements
)
105 std::swap(dst
[x
+ offset
], dst
[x
+ 2 + offset
]);
110 void CTextureBase::ClampToEdge()
112 if (m_pixels
== nullptr)
115 uint32_t imagePitch
= GetPitch(m_imageWidth
);
116 uint32_t imageRows
= GetRows(m_imageHeight
);
117 uint32_t texturePitch
= GetPitch(m_textureWidth
);
118 uint32_t textureRows
= GetRows(m_textureHeight
);
120 if (imagePitch
< texturePitch
)
122 uint32_t blockSize
= GetBlockSize();
123 unsigned char* src
= m_pixels
+ imagePitch
- blockSize
;
124 unsigned char* dst
= m_pixels
;
125 for (uint32_t y
= 0; y
< imageRows
; y
++)
127 for (uint32_t x
= imagePitch
; x
< texturePitch
; x
+= blockSize
)
128 memcpy(dst
+ x
, src
, blockSize
);
133 if (imageRows
< textureRows
)
135 unsigned char* dst
= m_pixels
+ imageRows
* texturePitch
;
136 for (uint32_t y
= imageRows
; y
< textureRows
; y
++)
138 memcpy(dst
, dst
- texturePitch
, texturePitch
);
144 uint32_t CTextureBase::GetPitch(uint32_t width
) const
146 uint32_t blockWidth
= GetBlockWidth();
147 uint32_t pitch
= ((width
+ blockWidth
- 1) / blockWidth
) * GetBlockSize();
149 // For the GPU, RGB8 needs to be aligned to 32 bit
150 if (m_textureFormat
== KD_TEX_FMT_SDR_RGB8
)
151 pitch
= ((pitch
+ 3) / 4) * 4;
156 uint32_t CTextureBase::GetRows(uint32_t height
) const
158 uint32_t blockHeight
= GetBlockHeight();
159 return (height
+ blockHeight
- 1) / blockHeight
;
162 uint32_t CTextureBase::GetBlockWidth() const
164 switch (m_textureFormat
)
166 case KD_TEX_FMT_SDR_R8
:
167 case KD_TEX_FMT_SDR_RG8
:
168 case KD_TEX_FMT_SDR_R5G6B5
:
169 case KD_TEX_FMT_SDR_RGB5_A1
:
170 case KD_TEX_FMT_SDR_RGBA4
:
171 case KD_TEX_FMT_SDR_RGB8
:
172 case KD_TEX_FMT_SDR_RGBA8
:
173 case KD_TEX_FMT_SDR_BGRA8
:
174 case KD_TEX_FMT_HDR_R16f
:
175 case KD_TEX_FMT_HDR_RG16f
:
176 case KD_TEX_FMT_HDR_R11F_G11F_B10F
:
177 case KD_TEX_FMT_HDR_RGB9_E5
:
178 case KD_TEX_FMT_HDR_RGB10_A2
:
179 case KD_TEX_FMT_HDR_RGBA16f
:
181 case KD_TEX_FMT_YUV_YUYV8
:
183 case KD_TEX_FMT_S3TC_RGB8
:
184 case KD_TEX_FMT_S3TC_RGB8_A1
:
185 case KD_TEX_FMT_S3TC_RGB8_A4
:
186 case KD_TEX_FMT_S3TC_RGBA8
:
187 case KD_TEX_FMT_RGTC_R11
:
188 case KD_TEX_FMT_RGTC_RG11
:
189 case KD_TEX_FMT_BPTC_RGB16F
:
190 case KD_TEX_FMT_BPTC_RGBA8
:
191 case KD_TEX_FMT_ETC1
:
192 case KD_TEX_FMT_ETC2_RGB8
:
193 case KD_TEX_FMT_ETC2_RGB8_A1
:
194 case KD_TEX_FMT_ETC2_RGBA8
:
195 case KD_TEX_FMT_ETC2_R11
:
196 case KD_TEX_FMT_ETC2_RG11
:
197 case KD_TEX_FMT_ASTC_LDR_4x4
:
198 case KD_TEX_FMT_ASTC_HDR_4x4
:
200 case KD_TEX_FMT_ASTC_LDR_5x4
:
201 case KD_TEX_FMT_ASTC_LDR_5x5
:
202 case KD_TEX_FMT_ASTC_HDR_5x4
:
203 case KD_TEX_FMT_ASTC_HDR_5x5
:
205 case KD_TEX_FMT_ASTC_LDR_6x5
:
206 case KD_TEX_FMT_ASTC_LDR_6x6
:
207 case KD_TEX_FMT_ASTC_HDR_6x5
:
208 case KD_TEX_FMT_ASTC_HDR_6x6
:
210 case KD_TEX_FMT_ASTC_LDR_8x5
:
211 case KD_TEX_FMT_ASTC_LDR_8x6
:
212 case KD_TEX_FMT_ASTC_LDR_8x8
:
213 case KD_TEX_FMT_ASTC_HDR_8x5
:
214 case KD_TEX_FMT_ASTC_HDR_8x6
:
215 case KD_TEX_FMT_ASTC_HDR_8x8
:
217 case KD_TEX_FMT_ASTC_LDR_10x5
:
218 case KD_TEX_FMT_ASTC_LDR_10x6
:
219 case KD_TEX_FMT_ASTC_LDR_10x8
:
220 case KD_TEX_FMT_ASTC_LDR_10x10
:
221 case KD_TEX_FMT_ASTC_HDR_10x5
:
222 case KD_TEX_FMT_ASTC_HDR_10x6
:
223 case KD_TEX_FMT_ASTC_HDR_10x8
:
224 case KD_TEX_FMT_ASTC_HDR_10x10
:
226 case KD_TEX_FMT_ASTC_LDR_12x10
:
227 case KD_TEX_FMT_ASTC_LDR_12x12
:
228 case KD_TEX_FMT_ASTC_HDR_12x10
:
229 case KD_TEX_FMT_ASTC_HDR_12x12
:
236 uint32_t CTextureBase::GetBlockHeight() const
238 switch (m_textureFormat
)
240 case KD_TEX_FMT_SDR_R8
:
241 case KD_TEX_FMT_SDR_RG8
:
242 case KD_TEX_FMT_SDR_R5G6B5
:
243 case KD_TEX_FMT_SDR_RGB5_A1
:
244 case KD_TEX_FMT_SDR_RGBA4
:
245 case KD_TEX_FMT_SDR_RGB8
:
246 case KD_TEX_FMT_SDR_RGBA8
:
247 case KD_TEX_FMT_SDR_BGRA8
:
248 case KD_TEX_FMT_HDR_R16f
:
249 case KD_TEX_FMT_HDR_RG16f
:
250 case KD_TEX_FMT_HDR_R11F_G11F_B10F
:
251 case KD_TEX_FMT_HDR_RGB9_E5
:
252 case KD_TEX_FMT_HDR_RGB10_A2
:
253 case KD_TEX_FMT_HDR_RGBA16f
:
254 case KD_TEX_FMT_YUV_YUYV8
:
256 case KD_TEX_FMT_S3TC_RGB8
:
257 case KD_TEX_FMT_S3TC_RGB8_A1
:
258 case KD_TEX_FMT_S3TC_RGB8_A4
:
259 case KD_TEX_FMT_S3TC_RGBA8
:
260 case KD_TEX_FMT_RGTC_R11
:
261 case KD_TEX_FMT_RGTC_RG11
:
262 case KD_TEX_FMT_BPTC_RGB16F
:
263 case KD_TEX_FMT_BPTC_RGBA8
:
264 case KD_TEX_FMT_ETC1
:
265 case KD_TEX_FMT_ETC2_RGB8
:
266 case KD_TEX_FMT_ETC2_RGB8_A1
:
267 case KD_TEX_FMT_ETC2_RGBA8
:
268 case KD_TEX_FMT_ETC2_R11
:
269 case KD_TEX_FMT_ETC2_RG11
:
270 case KD_TEX_FMT_ASTC_LDR_4x4
:
271 case KD_TEX_FMT_ASTC_LDR_5x4
:
272 case KD_TEX_FMT_ASTC_HDR_4x4
:
273 case KD_TEX_FMT_ASTC_HDR_5x4
:
275 case KD_TEX_FMT_ASTC_LDR_5x5
:
276 case KD_TEX_FMT_ASTC_LDR_6x5
:
277 case KD_TEX_FMT_ASTC_LDR_8x5
:
278 case KD_TEX_FMT_ASTC_LDR_10x5
:
279 case KD_TEX_FMT_ASTC_HDR_5x5
:
280 case KD_TEX_FMT_ASTC_HDR_6x5
:
281 case KD_TEX_FMT_ASTC_HDR_8x5
:
282 case KD_TEX_FMT_ASTC_HDR_10x5
:
284 case KD_TEX_FMT_ASTC_LDR_6x6
:
285 case KD_TEX_FMT_ASTC_LDR_8x6
:
286 case KD_TEX_FMT_ASTC_LDR_10x6
:
287 case KD_TEX_FMT_ASTC_HDR_6x6
:
288 case KD_TEX_FMT_ASTC_HDR_8x6
:
289 case KD_TEX_FMT_ASTC_HDR_10x6
:
291 case KD_TEX_FMT_ASTC_LDR_8x8
:
292 case KD_TEX_FMT_ASTC_LDR_10x8
:
293 case KD_TEX_FMT_ASTC_HDR_8x8
:
294 case KD_TEX_FMT_ASTC_HDR_10x8
:
296 case KD_TEX_FMT_ASTC_LDR_10x10
:
297 case KD_TEX_FMT_ASTC_LDR_12x10
:
298 case KD_TEX_FMT_ASTC_HDR_10x10
:
299 case KD_TEX_FMT_ASTC_HDR_12x10
:
301 case KD_TEX_FMT_ASTC_LDR_12x12
:
302 case KD_TEX_FMT_ASTC_HDR_12x12
:
309 uint32_t CTextureBase::GetBlockSize() const
311 switch (m_textureFormat
)
313 case KD_TEX_FMT_SDR_R8
:
315 case KD_TEX_FMT_SDR_RG8
:
316 case KD_TEX_FMT_SDR_R5G6B5
:
317 case KD_TEX_FMT_SDR_RGB5_A1
:
318 case KD_TEX_FMT_SDR_RGBA4
:
319 case KD_TEX_FMT_HDR_R16f
:
321 case KD_TEX_FMT_SDR_RGB8
:
323 case KD_TEX_FMT_SDR_RGBA8
:
324 case KD_TEX_FMT_SDR_BGRA8
:
325 case KD_TEX_FMT_HDR_RG16f
:
326 case KD_TEX_FMT_HDR_R11F_G11F_B10F
:
327 case KD_TEX_FMT_HDR_RGB9_E5
:
328 case KD_TEX_FMT_HDR_RGB10_A2
:
329 case KD_TEX_FMT_YUV_YUYV8
:
331 case KD_TEX_FMT_HDR_RGBA16f
:
332 case KD_TEX_FMT_S3TC_RGB8
:
333 case KD_TEX_FMT_S3TC_RGB8_A1
:
334 case KD_TEX_FMT_RGTC_R11
:
335 case KD_TEX_FMT_ETC1
:
336 case KD_TEX_FMT_ETC2_RGB8
:
337 case KD_TEX_FMT_ETC2_RGB8_A1
:
338 case KD_TEX_FMT_ETC2_R11
:
340 case KD_TEX_FMT_S3TC_RGB8_A4
:
341 case KD_TEX_FMT_S3TC_RGBA8
:
342 case KD_TEX_FMT_RGTC_RG11
:
343 case KD_TEX_FMT_BPTC_RGB16F
:
344 case KD_TEX_FMT_BPTC_RGBA8
:
345 case KD_TEX_FMT_ETC2_RG11
:
346 case KD_TEX_FMT_ETC2_RGBA8
:
347 case KD_TEX_FMT_ASTC_LDR_4x4
:
348 case KD_TEX_FMT_ASTC_LDR_5x4
:
349 case KD_TEX_FMT_ASTC_LDR_5x5
:
350 case KD_TEX_FMT_ASTC_LDR_6x5
:
351 case KD_TEX_FMT_ASTC_LDR_6x6
:
352 case KD_TEX_FMT_ASTC_LDR_8x5
:
353 case KD_TEX_FMT_ASTC_LDR_8x6
:
354 case KD_TEX_FMT_ASTC_LDR_8x8
:
355 case KD_TEX_FMT_ASTC_LDR_10x5
:
356 case KD_TEX_FMT_ASTC_LDR_10x6
:
357 case KD_TEX_FMT_ASTC_LDR_10x8
:
358 case KD_TEX_FMT_ASTC_LDR_10x10
:
359 case KD_TEX_FMT_ASTC_LDR_12x10
:
360 case KD_TEX_FMT_ASTC_LDR_12x12
:
361 case KD_TEX_FMT_ASTC_HDR_4x4
:
362 case KD_TEX_FMT_ASTC_HDR_5x4
:
363 case KD_TEX_FMT_ASTC_HDR_5x5
:
364 case KD_TEX_FMT_ASTC_HDR_6x5
:
365 case KD_TEX_FMT_ASTC_HDR_6x6
:
366 case KD_TEX_FMT_ASTC_HDR_8x5
:
367 case KD_TEX_FMT_ASTC_HDR_8x6
:
368 case KD_TEX_FMT_ASTC_HDR_8x8
:
369 case KD_TEX_FMT_ASTC_HDR_10x5
:
370 case KD_TEX_FMT_ASTC_HDR_10x6
:
371 case KD_TEX_FMT_ASTC_HDR_10x8
:
372 case KD_TEX_FMT_ASTC_HDR_10x10
:
373 case KD_TEX_FMT_ASTC_HDR_12x10
:
374 case KD_TEX_FMT_ASTC_HDR_12x12
:
381 void CTextureBase::SetKDFormat(XB_FMT xbFMT
)
386 m_textureFormat
= KD_TEX_FMT_S3TC_RGB8
;
389 m_textureFormat
= KD_TEX_FMT_S3TC_RGB8_A4
;
392 m_textureFormat
= KD_TEX_FMT_S3TC_RGBA8
;
394 case XB_FMT_A8R8G8B8
:
395 m_textureFormat
= KD_TEX_FMT_SDR_BGRA8
;
398 m_textureFormat
= KD_TEX_FMT_SDR_R8
;
399 m_textureSwizzle
= KD_TEX_SWIZ_111R
;
402 m_textureFormat
= KD_TEX_FMT_SDR_RGBA8
;
405 m_textureFormat
= KD_TEX_FMT_SDR_RGB8
;
408 case XB_FMT_DXT5_YCoCg
:
410 m_textureFormat
= KD_TEX_FMT_UNKNOWN
;