1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
// This software contains source code provided by NVIDIA Corporation.
// License: http://developer.download.nvidia.com/licenses/general_license.txt
// Modified DDS class from NVIDIA SDK.
#ifndef __NV_DDS_H__
#define __NV_DDS_H__
#include <string>
#include <vector>
#include <cstdio>
#include <assert.h>
namespace nv_dds
{
// surface description flags
const unsigned int DDSF_CAPS = 0x00000001;
const unsigned int DDSF_HEIGHT = 0x00000002;
const unsigned int DDSF_WIDTH = 0x00000004;
const unsigned int DDSF_PITCH = 0x00000008;
const unsigned int DDSF_PIXELFORMAT = 0x00001000;
const unsigned int DDSF_MIPMAPCOUNT = 0x00020000;
const unsigned int DDSF_LINEARSIZE = 0x00080000;
const unsigned int DDSF_DEPTH = 0x00800000;
// pixel format flags
const unsigned int DDSF_ALPHAPIXELS = 0x00000001;
const unsigned int DDSF_FOURCC = 0x00000004;
const unsigned int DDSF_RGB = 0x00000040;
const unsigned int DDSF_RGBA = 0x00000041;
// dwCaps1 flags
const unsigned int DDSF_COMPLEX = 0x00000008;
const unsigned int DDSF_TEXTURE = 0x00001000;
const unsigned int DDSF_MIPMAP = 0x00400000;
// dwCaps2 flags
const unsigned int DDSF_CUBEMAP = 0x00000200;
const unsigned int DDSF_CUBEMAP_POSITIVEX = 0x00000400;
const unsigned int DDSF_CUBEMAP_NEGATIVEX = 0x00000800;
const unsigned int DDSF_CUBEMAP_POSITIVEY = 0x00001000;
const unsigned int DDSF_CUBEMAP_NEGATIVEY = 0x00002000;
const unsigned int DDSF_CUBEMAP_POSITIVEZ = 0x00004000;
const unsigned int DDSF_CUBEMAP_NEGATIVEZ = 0x00008000;
const unsigned int DDSF_CUBEMAP_ALL_FACES = 0x0000FC00;
const unsigned int DDSF_VOLUME = 0x00200000;
// compressed texture types
const unsigned int FOURCC_DXT1 = 0x31545844; //(MAKEFOURCC('D','X','T','1'))
const unsigned int FOURCC_DXT3 = 0x33545844; //(MAKEFOURCC('D','X','T','3'))
const unsigned int FOURCC_DXT5 = 0x35545844; //(MAKEFOURCC('D','X','T','5'))
struct DXTColBlock
{
unsigned short col0;
unsigned short col1;
unsigned char row[4];
};
struct DXT3AlphaBlock
{
unsigned short row[4];
};
struct DXT5AlphaBlock
{
unsigned char alpha0;
unsigned char alpha1;
unsigned char row[6];
};
struct DDS_PIXELFORMAT
{
unsigned int dwSize;
unsigned int dwFlags;
unsigned int dwFourCC;
unsigned int dwRGBBitCount;
unsigned int dwRBitMask;
unsigned int dwGBitMask;
unsigned int dwBBitMask;
unsigned int dwABitMask;
};
struct DDS_HEADER
{
unsigned int dwSize;
unsigned int dwFlags;
unsigned int dwHeight;
unsigned int dwWidth;
unsigned int dwPitchOrLinearSize;
unsigned int dwDepth;
unsigned int dwMipMapCount;
unsigned int dwReserved1[11];
DDS_PIXELFORMAT ddspf;
unsigned int dwCaps1;
unsigned int dwCaps2;
unsigned int dwReserved2[3];
};
enum TextureType
{
TextureNone,
TextureFlat, // 1D, 2D, and rectangle textures
Texture3D,
TextureCubemap
};
class CSurface
{
public:
CSurface();
CSurface(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels);
CSurface(const CSurface ©): CSurface() { *this = copy; }
CSurface(CSurface &&surf): CSurface() { *this = std::move(surf); }
CSurface &operator= (const CSurface &rhs);
CSurface &operator= (CSurface &&rhs) noexcept;
virtual ~CSurface() { clear(); }
operator unsigned char*() const;
virtual void create(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels);
virtual void clear();
inline unsigned int get_width() const { return m_width; }
inline unsigned int get_height() const { return m_height; }
inline unsigned int get_depth() const { return m_depth; }
inline unsigned int get_size() const { return m_size; }
private:
unsigned int m_width;
unsigned int m_height;
unsigned int m_depth;
unsigned int m_size;
unsigned char *m_pixels;
};
class CTexture : public CSurface
{
friend class CDDSImage;
public:
CTexture(): CSurface() {}
CTexture(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels);
CTexture(const CTexture ©): CTexture() { *this = copy; }
CTexture(CTexture &&text): CTexture() { *this = std::move(text); }
CTexture &operator=(const CTexture &rhs);
CTexture &operator=(CTexture &&rhs) noexcept;
void create(unsigned int w, unsigned int h, unsigned int d, unsigned int imgsize, const unsigned char *pixels) override;
void clear() override;
inline const CSurface &get_mipmap(unsigned int index) const
{
assert(!m_mipmaps.empty());
assert(index < m_mipmaps.size());
return m_mipmaps[index];
}
inline void add_mipmap()
{
m_mipmaps.emplace_back();
}
inline unsigned int get_num_mipmaps() const { return (unsigned int)m_mipmaps.size(); }
protected:
inline CSurface &get_mipmap(unsigned int index)
{
assert(!m_mipmaps.empty());
assert(index < m_mipmaps.size());
return m_mipmaps[index];
}
private:
std::vector<CSurface> m_mipmaps;
};
class CDDSImage
{
public:
CDDSImage();
CDDSImage(const CDDSImage& img) { *this = img; }
CDDSImage(CDDSImage&& img) { *this = std::move(img); }
CDDSImage& operator = (const CDDSImage& img) {
m_format = img.m_format;
m_components = img.m_components;
m_type = img.m_type;
m_valid = img.m_valid;
m_images = img.m_images;
return *this;
}
CDDSImage& operator = (CDDSImage&& img) {
m_format = img.m_format;
m_components = img.m_components;
m_type = img.m_type;
m_valid = img.m_valid;
m_images = std::move(img.m_images);
return *this;
}
#if 0
void create_textureFlat(unsigned int format, unsigned int components, const CTexture &baseImage);
void create_texture3D(unsigned int format, unsigned int components, const CTexture &baseImage);
void create_textureCubemap(unsigned int format, unsigned int components,
const CTexture &positiveX, const CTexture &negativeX,
const CTexture &positiveY, const CTexture &negativeY,
const CTexture &positiveZ, const CTexture &negativeZ);
#endif
void clear();
bool load(std::string filename, bool flipImage = true);
bool save(std::string filename, bool flipImage = true) const;
bool upload_texture1D() const;
bool upload_texture2D(unsigned int imageIndex, int target) const;
bool upload_texture3D() const;
bool upload_textureRectangle() const;
bool upload_textureCubemap() const;
inline operator unsigned char*()
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0];
}
inline unsigned int get_width() const
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_width();
}
inline unsigned int get_height() const
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_height();
}
inline unsigned int get_depth() const
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_depth();
}
inline unsigned int get_size() const
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_size();
}
inline unsigned int get_num_mipmaps() const
{
assert(m_valid);
assert(!m_images.empty());
return m_images[0].get_num_mipmaps();
}
inline const CSurface &get_mipmap(unsigned int index) const
{
assert(m_valid);
assert(!m_images.empty());
assert(index < m_images[0].get_num_mipmaps());
return m_images[0].get_mipmap(index);
}
inline const CTexture &get_cubemap_face(unsigned int face) const
{
assert(m_valid);
assert(!m_images.empty());
assert(m_images.size() == 6);
assert(m_type == TextureCubemap);
assert(face < 6);
return m_images[face];
}
inline unsigned int get_components() const { return m_components; }
inline unsigned int get_format() const { return m_format; }
inline TextureType get_type() const { return m_type; }
bool is_compressed() const;
inline bool is_cubemap() const { return (m_type == TextureCubemap); }
inline bool is_volume() const { return (m_type == Texture3D); }
inline bool is_valid() const { return m_valid; }
inline bool is_dword_aligned() const
{
assert(m_valid);
int dwordLineSize = get_dword_aligned_linesize(get_width(), m_components*8);
int curLineSize = get_width() * m_components;
return (dwordLineSize == curLineSize);
}
private:
unsigned int clamp_size(unsigned int size) const;
unsigned int size_dxtc(unsigned int width, unsigned int height) const;
unsigned int size_rgb(unsigned int width, unsigned int height) const;
// calculates 4-byte aligned width of image
inline unsigned int get_dword_aligned_linesize(unsigned int width, unsigned int bpp) const
{
return ((width * bpp + 31) & -32) >> 3;
}
void flip(CSurface &surface) const;
void flip_texture(CTexture &texture) const;
void swap(void *byte1, void *byte2, unsigned int size) const;
void flip_blocks_dxtc1(DXTColBlock *line, unsigned int numBlocks) const;
void flip_blocks_dxtc3(DXTColBlock *line, unsigned int numBlocks) const;
void flip_blocks_dxtc5(DXTColBlock *line, unsigned int numBlocks) const;
void flip_dxt5_alpha(DXT5AlphaBlock *block) const;
bool write_texture(const CTexture &texture, FILE *fp) const;
unsigned int m_format;
unsigned int m_components;
TextureType m_type;
bool m_valid;
std::vector<CTexture> m_images;
};
}
#endif
|