Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/imbuf/intern/dds')
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.cpp79
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.h8
-rw-r--r--source/blender/imbuf/intern/dds/CMakeLists.txt9
-rw-r--r--source/blender/imbuf/intern/dds/Color.h2
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.cpp188
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.h21
-rw-r--r--source/blender/imbuf/intern/dds/Common.h8
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp489
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.h22
-rw-r--r--source/blender/imbuf/intern/dds/Image.cpp7
-rw-r--r--source/blender/imbuf/intern/dds/Image.h2
-rw-r--r--source/blender/imbuf/intern/dds/PixelFormat.h34
-rw-r--r--source/blender/imbuf/intern/dds/Stream.cpp2
-rw-r--r--source/blender/imbuf/intern/dds/Stream.h2
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp24
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.h2
16 files changed, 703 insertions, 196 deletions
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp
index 2989361efe6..0d17f16532b 100644
--- a/source/blender/imbuf/intern/dds/BlockDXT.cpp
+++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -123,6 +123,53 @@ uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const
}
}
+
+uint BlockDXT1::evaluatePaletteNV5x(Color32 color_array[4]) const
+{
+ // Does bit expansion before interpolation.
+ color_array[0].b = (3 * col0.b * 22) / 8;
+ color_array[0].g = (col0.g << 2) | (col0.g >> 4);
+ color_array[0].r = (3 * col0.r * 22) / 8;
+ color_array[0].a = 0xFF;
+
+ color_array[1].r = (3 * col1.r * 22) / 8;
+ color_array[1].g = (col1.g << 2) | (col1.g >> 4);
+ color_array[1].b = (3 * col1.b * 22) / 8;
+ color_array[1].a = 0xFF;
+
+ int gdiff = color_array[1].g - color_array[0].g;
+
+ if( col0.u > col1.u ) {
+ // Four-color block: derive the other two colors.
+ color_array[2].r = ((2 * col0.r + col1.r) * 22) / 8;
+ color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 80) / 256;
+ color_array[2].b = ((2 * col0.b + col1.b) * 22) / 8;
+ color_array[2].a = 0xFF;
+
+ color_array[3].r = ((2 * col1.r + col0.r) * 22) / 8;
+ color_array[3].g = (256 * color_array[1].g - gdiff / 4 + 128 - gdiff * 80) / 256;
+ color_array[3].b = ((2 * col1.b + col0.b) * 22) / 8;
+ color_array[3].a = 0xFF;
+
+ return 4;
+ }
+ else {
+ // Three-color block: derive the other color.
+ color_array[2].r = ((col0.r + col1.r) * 33) / 8;
+ color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 128) / 256;
+ color_array[2].b = ((col0.b + col1.b) * 33) / 8;
+ color_array[2].a = 0xFF;
+
+ // Set all components to 0 to match DXT specs.
+ color_array[3].r = 0x00; // color_array[2].r;
+ color_array[3].g = 0x00; // color_array[2].g;
+ color_array[3].b = 0x00; // color_array[2].b;
+ color_array[3].a = 0x00;
+
+ return 3;
+ }
+}
+
// Evaluate palette assuming 3 color block.
void BlockDXT1::evaluatePalette3(Color32 color_array[4]) const
{
@@ -174,6 +221,7 @@ void BlockDXT1::evaluatePalette4(Color32 color_array[4]) const
color_array[3].a = 0xFF;
}
+
void BlockDXT1::decodeBlock(ColorBlock * block) const
{
// Decode color block.
@@ -189,6 +237,21 @@ void BlockDXT1::decodeBlock(ColorBlock * block) const
}
}
+void BlockDXT1::decodeBlockNV5x(ColorBlock * block) const
+{
+ // Decode color block.
+ Color32 color_array[4];
+ evaluatePaletteNV5x(color_array);
+
+ // Write color block.
+ for( uint j = 0; j < 4; j++ ) {
+ for( uint i = 0; i < 4; i++ ) {
+ uint idx = (row[j] >> (2 * i)) & 3;
+ block->color(i, j) = color_array[idx];
+ }
+ }
+}
+
void BlockDXT1::setIndices(int * idx)
{
indices = 0;
@@ -225,6 +288,12 @@ void BlockDXT3::decodeBlock(ColorBlock * block) const
alpha.decodeBlock(block);
}
+void BlockDXT3::decodeBlockNV5x(ColorBlock * block) const
+{
+ color.decodeBlockNV5x(block);
+ alpha.decodeBlock(block);
+}
+
void AlphaBlockDXT3::decodeBlock(ColorBlock * block) const
{
block->color(0x0).a = (alpha0 << 4) | alpha0;
@@ -394,7 +463,15 @@ void BlockDXT5::decodeBlock(ColorBlock * block) const
// Decode alpha.
alpha.decodeBlock(block);
+}
+void BlockDXT5::decodeBlockNV5x(ColorBlock * block) const
+{
+ // Decode color.
+ color.decodeBlockNV5x(block);
+
+ // Decode alpha.
+ alpha.decodeBlock(block);
}
/// Flip DXT5 block vertically.
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h
index 7c5b9acffd2..aa0c1c509ca 100644
--- a/source/blender/imbuf/intern/dds/BlockDXT.h
+++ b/source/blender/imbuf/intern/dds/BlockDXT.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -78,11 +78,13 @@ struct BlockDXT1
bool isFourColorMode() const;
uint evaluatePalette(Color32 color_array[4]) const;
- uint evaluatePaletteFast(Color32 color_array[4]) const;
+ uint evaluatePaletteNV5x(Color32 color_array[4]) const;
+
void evaluatePalette3(Color32 color_array[4]) const;
void evaluatePalette4(Color32 color_array[4]) const;
void decodeBlock(ColorBlock * block) const;
+ void decodeBlockNV5x(ColorBlock * block) const;
void setIndices(int * idx);
@@ -136,6 +138,7 @@ struct BlockDXT3
BlockDXT1 color;
void decodeBlock(ColorBlock * block) const;
+ void decodeBlockNV5x(ColorBlock * block) const;
void flip4();
void flip2();
@@ -213,6 +216,7 @@ struct BlockDXT5
BlockDXT1 color;
void decodeBlock(ColorBlock * block) const;
+ void decodeBlockNV5x(ColorBlock * block) const;
void flip4();
void flip2();
diff --git a/source/blender/imbuf/intern/dds/CMakeLists.txt b/source/blender/imbuf/intern/dds/CMakeLists.txt
index 7564287ce4a..53822b830f7 100644
--- a/source/blender/imbuf/intern/dds/CMakeLists.txt
+++ b/source/blender/imbuf/intern/dds/CMakeLists.txt
@@ -28,13 +28,16 @@ set(INC
.
..
../..
- ./intern/include
- ../../../blenlib
../../../blenkernel
+ ../../../blenlib
../../../makesdna
../../../../../intern/guardedalloc
)
+set(INC_SYS
+
+)
+
set(SRC
BlockDXT.cpp
ColorBlock.cpp
@@ -48,4 +51,4 @@ if(WITH_IMAGE_DDS)
add_definitions(-DWITH_DDS)
endif()
-blender_add_lib(bf_imbuf_dds "${SRC}" "${INC}")
+blender_add_lib(bf_imbuf_dds "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/imbuf/intern/dds/Color.h b/source/blender/imbuf/intern/dds/Color.h
index 5efc259b795..42ed34daf76 100644
--- a/source/blender/imbuf/intern/dds/Color.h
+++ b/source/blender/imbuf/intern/dds/Color.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp
index 711d1b54cfa..edb69934231 100644
--- a/source/blender/imbuf/intern/dds/ColorBlock.cpp
+++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -83,65 +83,90 @@ ColorBlock::ColorBlock(const Image * img, uint x, uint y)
void ColorBlock::init(const Image * img, uint x, uint y)
{
- const uint bw = min(img->width() - x, 4U);
- const uint bh = min(img->height() - y, 4U);
+ init(img->width(), img->height(), (const uint *)img->pixels(), x, y);
+}
- static int remainder[] = {
- 0, 0, 0, 0,
- 0, 1, 0, 1,
- 0, 1, 2, 0,
- 0, 1, 2, 3,
- };
+void ColorBlock::init(uint w, uint h, const uint * data, uint x, uint y)
+{
+ const uint bw = min(w - x, 4U);
+ const uint bh = min(h - y, 4U);
- // Blocks that are smaller than 4x4 are handled by repeating the pixels.
- // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
+ // Blocks that are smaller than 4x4 are handled by repeating the pixels.
+ // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
+ // @@ Ideally we should zero the weights of the pixels out of range.
- for(uint i = 0; i < 4; i++) {
- //const int by = i % bh;
- const int by = remainder[(bh - 1) * 4 + i];
- for(uint e = 0; e < 4; e++) {
- //const int bx = e % bw;
- const int bx = remainder[(bw - 1) * 4 + e];
- color(e, i) = img->pixel(x + bx, y + by);
- }
- }
-}
+ for (uint i = 0; i < 4; i++)
+ {
+ const int by = i % bh;
+
+ for (uint e = 0; e < 4; e++)
+ {
+ const int bx = e % bw;
+ const uint idx = (y + by) * w + x + bx;
+ color(e, i).u = data[idx];
+ }
+ }
+}
-void ColorBlock::swizzleDXT5n()
+void ColorBlock::init(uint w, uint h, const float * data, uint x, uint y)
{
- for(int i = 0; i < 16; i++)
+ const uint bw = min(w - x, 4U);
+ const uint bh = min(h - y, 4U);
+
+ // Blocks that are smaller than 4x4 are handled by repeating the pixels.
+ // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
+ // @@ Ideally we should zero the weights of the pixels out of range.
+
+ uint srcPlane = w * h;
+
+ for (uint i = 0; i < 4; i++)
{
- Color32 c = m_color[i];
- m_color[i] = Color32(0xFF, c.g, 0, c.r);
+ const uint by = i % bh;
+
+ for (uint e = 0; e < 4; e++)
+ {
+ const uint bx = e % bw;
+ const uint idx = ((y + by) * w + x + bx);
+
+ Color32 & c = color(e, i);
+ c.r = uint8(255 * clamp(data[idx + 0 * srcPlane], 0.0f, 1.0f)); // @@ Is this the right way to quantize floats to bytes?
+ c.g = uint8(255 * clamp(data[idx + 1 * srcPlane], 0.0f, 1.0f));
+ c.b = uint8(255 * clamp(data[idx + 2 * srcPlane], 0.0f, 1.0f));
+ c.a = uint8(255 * clamp(data[idx + 3 * srcPlane], 0.0f, 1.0f));
+ }
}
}
-void ColorBlock::splatX()
+static inline uint8 component(Color32 c, uint i)
{
- for(int i = 0; i < 16; i++)
- {
- uint8 x = m_color[i].r;
- m_color[i] = Color32(x, x, x, x);
- }
+ if (i == 0) return c.r;
+ if (i == 1) return c.g;
+ if (i == 2) return c.b;
+ if (i == 3) return c.a;
+ if (i == 4) return 0xFF;
+ return 0;
}
-void ColorBlock::splatY()
+void ColorBlock::swizzle(uint x, uint y, uint z, uint w)
{
- for(int i = 0; i < 16; i++)
+ for (int i = 0; i < 16; i++)
{
- uint8 y = m_color[i].g;
- m_color[i] = Color32(y, y, y, y);
+ Color32 c = m_color[i];
+ m_color[i].r = component(c, x);
+ m_color[i].g = component(c, y);
+ m_color[i].b = component(c, z);
+ m_color[i].a = component(c, w);
}
}
+
/// Returns true if the block has a single color.
-bool ColorBlock::isSingleColor() const
+bool ColorBlock::isSingleColor(Color32 mask/*= Color32(0xFF, 0xFF, 0xFF, 0x00)*/) const
{
- Color32 mask(0xFF, 0xFF, 0xFF, 0x00);
uint u = m_color[0].u & mask.u;
- for(int i = 1; i < 16; i++)
+ for (int i = 1; i < 16; i++)
{
if (u != (m_color[i].u & mask.u))
{
@@ -152,6 +177,7 @@ bool ColorBlock::isSingleColor() const
return true;
}
+/*
/// Returns true if the block has a single color, ignoring transparent pixels.
bool ColorBlock::isSingleColorNoAlpha() const
{
@@ -159,7 +185,7 @@ bool ColorBlock::isSingleColorNoAlpha() const
int i;
for(i = 0; i < 16; i++)
{
- if (m_color[i].a != 0) c = m_color[i];
+ if (m_color[i].a != 0) c = m_color[i];
}
Color32 mask(0xFF, 0xFF, 0xFF, 0x00);
@@ -175,9 +201,10 @@ bool ColorBlock::isSingleColorNoAlpha() const
return true;
}
+*/
/// Count number of unique colors in this color block.
-uint ColorBlock::countUniqueColors() const
+/*uint ColorBlock::countUniqueColors() const
{
uint count = 0;
@@ -197,9 +224,9 @@ uint ColorBlock::countUniqueColors() const
}
return count;
-}
+}*/
-/// Get average color of the block.
+/*/// Get average color of the block.
Color32 ColorBlock::averageColor() const
{
uint r, g, b, a;
@@ -213,7 +240,7 @@ Color32 ColorBlock::averageColor() const
}
return Color32(uint8(r / 16), uint8(g / 16), uint8(b / 16), uint8(a / 16));
-}
+}*/
/// Return true if the block is not fully opaque.
bool ColorBlock::hasAlpha() const
@@ -225,6 +252,7 @@ bool ColorBlock::hasAlpha() const
return false;
}
+#if 0
/// Get diameter color range.
void ColorBlock::diameterRange(Color32 * start, Color32 * end) const
@@ -345,8 +373,9 @@ void ColorBlock::boundsRangeAlpha(Color32 * start, Color32 * end) const
*start = minColor;
*end = maxColor;
}
+#endif
-/// Sort colors by abosolute value in their 16 bit representation.
+/*/// Sort colors by abosolute value in their 16 bit representation.
void ColorBlock::sortColorsByAbsoluteValue()
{
// Dummy selection sort.
@@ -364,4 +393,75 @@ void ColorBlock::sortColorsByAbsoluteValue()
}
swap( m_color[a], m_color[max] );
}
+}*/
+
+
+/*/// Find extreme colors in the given axis.
+void ColorBlock::computeRange(Vector3::Arg axis, Color32 * start, Color32 * end) const
+{
+
+ int mini, maxi;
+ mini = maxi = 0;
+
+ float min, max;
+ min = max = dot(Vector3(m_color[0].r, m_color[0].g, m_color[0].b), axis);
+
+ for(uint i = 1; i < 16; i++)
+ {
+ const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b);
+
+ float val = dot(vec, axis);
+ if( val < min ) {
+ mini = i;
+ min = val;
+ }
+ else if( val > max ) {
+ maxi = i;
+ max = val;
+ }
+ }
+
+ *start = m_color[mini];
+ *end = m_color[maxi];
+}*/
+
+
+/*/// Sort colors in the given axis.
+void ColorBlock::sortColors(const Vector3 & axis)
+{
+ float luma_array[16];
+
+ for(uint i = 0; i < 16; i++) {
+ const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b);
+ luma_array[i] = dot(vec, axis);
+ }
+
+ // Dummy selection sort.
+ for( uint a = 0; a < 16; a++ ) {
+ uint min = a;
+ for( uint b = a+1; b < 16; b++ ) {
+ if( luma_array[b] < luma_array[min] ) {
+ min = b;
+ }
+ }
+ swap( luma_array[a], luma_array[min] );
+ swap( m_color[a], m_color[min] );
+ }
+}*/
+
+
+/*/// Get the volume of the color block.
+float ColorBlock::volume() const
+{
+ Box bounds;
+ bounds.clearBounds();
+
+ for(int i = 0; i < 16; i++) {
+ const Vector3 point(m_color[i].r, m_color[i].g, m_color[i].b);
+ bounds.addPointToBounds(point);
+ }
+
+ return bounds.volume();
}
+*/
+
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h
index dd40d21e8b3..d4e4e8a809f 100644
--- a/source/blender/imbuf/intern/dds/ColorBlock.h
+++ b/source/blender/imbuf/intern/dds/ColorBlock.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -51,26 +51,15 @@ struct ColorBlock
ColorBlock(const Image * img, uint x, uint y);
void init(const Image * img, uint x, uint y);
+ void init(uint w, uint h, const uint * data, uint x, uint y);
+ void init(uint w, uint h, const float * data, uint x, uint y);
- void swizzleDXT5n();
- void splatX();
- void splatY();
+ void swizzle(uint x, uint y, uint z, uint w); // 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0
- bool isSingleColor() const;
- bool isSingleColorNoAlpha() const;
- uint countUniqueColors() const;
- Color32 averageColor() const;
+ bool isSingleColor(Color32 mask = Color32(0xFF, 0xFF, 0xFF, 0x00)) const;
bool hasAlpha() const;
- void diameterRange(Color32 * start, Color32 * end) const;
- void luminanceRange(Color32 * start, Color32 * end) const;
- void boundsRange(Color32 * start, Color32 * end) const;
- void boundsRangeAlpha(Color32 * start, Color32 * end) const;
- void sortColorsByAbsoluteValue();
-
- float volume() const;
-
// Accessors
const Color32 * colors() const;
diff --git a/source/blender/imbuf/intern/dds/Common.h b/source/blender/imbuf/intern/dds/Common.h
index 25b743311d2..a6dcf69febf 100644
--- a/source/blender/imbuf/intern/dds/Common.h
+++ b/source/blender/imbuf/intern/dds/Common.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -55,4 +55,10 @@ typedef unsigned int uint;
typedef unsigned int uint32;
typedef unsigned long long uint64;
+// copied from nvtt src/nvimage/nvimage.h
+inline uint computePitch(uint w, uint bitsize, uint alignment)
+{
+ return ((w * bitsize + 8 * alignment - 1) / (8 * alignment)) * alignment;
+}
+
#endif
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
index ede82896554..971658ff482 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -69,12 +69,11 @@
#if !defined(MAKEFOURCC)
# define MAKEFOURCC(ch0, ch1, ch2, ch3) \
- ((uint)((unsigned char)(ch0)) | \
- ((uint)((unsigned char)(ch1)) << 8) | \
- ((uint)((unsigned char)(ch2)) << 16) | \
- ((uint)((unsigned char)(ch3)) << 24 ))
+ (uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | \
+ (uint(uint8(ch2)) << 16) | (uint(uint8(ch3)) << 24 ))
#endif
+static const uint FOURCC_NVTT = MAKEFOURCC('N', 'V', 'T', 'T');
static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
@@ -89,6 +88,8 @@ static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y');
static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0');
+static const uint FOURCC_UVER = MAKEFOURCC('U', 'V', 'E', 'R');
+
// 32 bit RGB formats.
static const uint D3DFMT_R8G8B8 = 20;
static const uint D3DFMT_A8R8G8B8 = 21;
@@ -160,7 +161,10 @@ static const uint DDPF_PALETTEINDEXED4 = 0x00000008U;
static const uint DDPF_PALETTEINDEXED8 = 0x00000020U;
static const uint DDPF_LUMINANCE = 0x00020000U;
static const uint DDPF_ALPHAPREMULT = 0x00008000U;
-static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag.
+
+// Custom NVTT flags.
+static const uint DDPF_NORMAL = 0x80000000U;
+static const uint DDPF_SRGB = 0x40000000U;
// DX10 formats.
enum DXGI_FORMAT
@@ -277,6 +281,20 @@ static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag.
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
+
+ DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
+ DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
+ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
+
+ DXGI_FORMAT_BC6H_TYPELESS = 94,
+ DXGI_FORMAT_BC6H_UF16 = 95,
+ DXGI_FORMAT_BC6H_SF16 = 96,
+
+ DXGI_FORMAT_BC7_TYPELESS = 97,
+ DXGI_FORMAT_BC7_UNORM = 98,
+ DXGI_FORMAT_BC7_UNORM_SRGB = 99,
};
enum D3D10_RESOURCE_DIMENSION
@@ -478,6 +496,63 @@ void mem_read(Stream & mem, DDSHeader & header)
}
}
+namespace
+{
+ struct FormatDescriptor
+ {
+ uint format;
+ uint bitcount;
+ uint rmask;
+ uint gmask;
+ uint bmask;
+ uint amask;
+ };
+
+ static const FormatDescriptor s_d3dFormats[] =
+ {
+ { D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 },
+ { D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, // DXGI_FORMAT_B8G8R8A8_UNORM
+ { D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, // DXGI_FORMAT_B8G8R8X8_UNORM
+ { D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, // DXGI_FORMAT_B5G6R5_UNORM
+ { D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 },
+ { D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, // DXGI_FORMAT_B5G5R5A1_UNORM
+ { D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 },
+ { D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 },
+ { D3DFMT_A8, 8, 0, 0, 0, 8 }, // DXGI_FORMAT_A8_UNORM
+ { D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 },
+ { D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 },
+ { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, // DXGI_FORMAT_R10G10B10A2
+ { D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, // DXGI_FORMAT_R8G8B8A8_UNORM
+ { D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 },
+ { D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, // DXGI_FORMAT_R16G16_UNORM
+ { D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 },
+ { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 },
+
+ { D3DFMT_L8, 8, 8, 0, 0, 0 }, // DXGI_FORMAT_R8_UNORM
+ { D3DFMT_L16, 16, 16, 0, 0, 0 }, // DXGI_FORMAT_R16_UNORM
+ };
+
+ static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]);
+
+} // namespace
+
+uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
+{
+ for (int i = 0; i < s_d3dFormatCount; i++)
+ {
+ if (s_d3dFormats[i].bitcount == bitcount &&
+ s_d3dFormats[i].rmask == rmask &&
+ s_d3dFormats[i].gmask == gmask &&
+ s_d3dFormats[i].bmask == bmask &&
+ s_d3dFormats[i].amask == amask)
+ {
+ return s_d3dFormats[i].format;
+ }
+ }
+
+ return 0;
+ }
+
DDSHeader::DDSHeader()
@@ -493,8 +568,8 @@ DDSHeader::DDSHeader()
for (uint i = 0; i < 11; i++) this->reserved[i] = 0;
// Store version information on the reserved header attributes.
- this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T');
- this->reserved[10] = (0 << 16) | (9 << 8) | (5); // major.minor.revision
+ this->reserved[9] = FOURCC_NVTT;
+ this->reserved[10] = (2 << 16) | (1 << 8) | (0); // major.minor.revision
this->pf.size = 32;
this->pf.flags = 0;
@@ -532,7 +607,7 @@ void DDSHeader::setHeight(uint h)
void DDSHeader::setDepth(uint d)
{
this->flags |= DDSD_DEPTH;
- this->height = d;
+ this->depth = d;
}
void DDSHeader::setMipmapCount(uint count)
@@ -540,7 +615,7 @@ void DDSHeader::setMipmapCount(uint count)
if (count == 0 || count == 1)
{
this->flags &= ~DDSD_MIPMAPCOUNT;
- this->mipmapcount = 0;
+ this->mipmapcount = 1;
if (this->caps.caps2 == 0) {
this->caps.caps1 = DDSCAPS_TEXTURE;
@@ -561,6 +636,7 @@ void DDSHeader::setMipmapCount(uint count)
void DDSHeader::setTexture2D()
{
this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
+ this->header10.arraySize = 1;
}
void DDSHeader::setTexture3D()
@@ -568,6 +644,7 @@ void DDSHeader::setTexture3D()
this->caps.caps2 = DDSCAPS2_VOLUME;
this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
+ this->header10.arraySize = 1;
}
void DDSHeader::setTextureCube()
@@ -599,21 +676,32 @@ void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
this->pf.flags = DDPF_FOURCC;
this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
- if (this->pf.fourcc == FOURCC_ATI2)
- {
- this->pf.bitcount = FOURCC_A2XY;
- }
- else
- {
- this->pf.bitcount = 0;
- }
+ this->pf.bitcount = 0;
+ this->pf.rmask = 0;
+ this->pf.gmask = 0;
+ this->pf.bmask = 0;
+ this->pf.amask = 0;
+}
+
+void DDSHeader::setFormatCode(uint32 code)
+{
+ // set fourcc pixel format.
+ this->pf.flags = DDPF_FOURCC;
+ this->pf.fourcc = code;
+ this->pf.bitcount = 0;
this->pf.rmask = 0;
this->pf.gmask = 0;
this->pf.bmask = 0;
this->pf.amask = 0;
}
+void DDSHeader::setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
+{
+ this->pf.bitcount = MAKEFOURCC(c0, c1, c2, c3);
+}
+
+
void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
{
// Make sure the masks are correct.
@@ -627,10 +715,24 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask
return;
}
- this->pf.flags = DDPF_RGB;
-
- if (amask != 0) {
- this->pf.flags |= DDPF_ALPHAPIXELS;
+ if (rmask != 0 || gmask != 0 || bmask != 0)
+ {
+ if (gmask == 0 && bmask == 0)
+ {
+ this->pf.flags = DDPF_LUMINANCE;
+ }
+ else
+ {
+ this->pf.flags = DDPF_RGB;
+ }
+
+ if (amask != 0) {
+ this->pf.flags |= DDPF_ALPHAPIXELS;
+ }
+ }
+ else if (amask != 0)
+ {
+ this->pf.flags |= DDPF_ALPHA;
}
if (bitcount == 0)
@@ -643,18 +745,16 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask
}
}
+ // D3DX functions do not like this:
+ this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
+ /*if (this->pf.fourcc) {
+ this->pf.flags |= DDPF_FOURCC;
+ }*/
+
if (!(bitcount > 0 && bitcount <= 32)) {
printf("DDS: bad bit count, pixel format not set\n");
return;
}
-
- // Align to 8.
- if (bitcount <= 8) bitcount = 8;
- else if (bitcount <= 16) bitcount = 16;
- else if (bitcount <= 24) bitcount = 24;
- else bitcount = 32;
-
- this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
this->pf.bitcount = bitcount;
this->pf.rmask = rmask;
this->pf.gmask = gmask;
@@ -675,10 +775,108 @@ void DDSHeader::setNormalFlag(bool b)
else this->pf.flags &= ~DDPF_NORMAL;
}
+void DDSHeader::setSrgbFlag(bool b)
+{
+ if (b) this->pf.flags |= DDPF_SRGB;
+ else this->pf.flags &= ~DDPF_SRGB;
+}
+
+void DDSHeader::setHasAlphaFlag(bool b)
+{
+ if (b) this->pf.flags |= DDPF_ALPHAPIXELS;
+ else this->pf.flags &= ~DDPF_ALPHAPIXELS;
+}
+
+void DDSHeader::setUserVersion(int version)
+{
+ this->reserved[7] = FOURCC_UVER;
+ this->reserved[8] = version;
+}
+
+/*
+void DDSHeader::swapBytes()
+{
+ this->fourcc = POSH_LittleU32(this->fourcc);
+ this->size = POSH_LittleU32(this->size);
+ this->flags = POSH_LittleU32(this->flags);
+ this->height = POSH_LittleU32(this->height);
+ this->width = POSH_LittleU32(this->width);
+ this->pitch = POSH_LittleU32(this->pitch);
+ this->depth = POSH_LittleU32(this->depth);
+ this->mipmapcount = POSH_LittleU32(this->mipmapcount);
+
+ for(int i = 0; i < 11; i++) {
+ this->reserved[i] = POSH_LittleU32(this->reserved[i]);
+ }
+
+ this->pf.size = POSH_LittleU32(this->pf.size);
+ this->pf.flags = POSH_LittleU32(this->pf.flags);
+ this->pf.fourcc = POSH_LittleU32(this->pf.fourcc);
+ this->pf.bitcount = POSH_LittleU32(this->pf.bitcount);
+ this->pf.rmask = POSH_LittleU32(this->pf.rmask);
+ this->pf.gmask = POSH_LittleU32(this->pf.gmask);
+ this->pf.bmask = POSH_LittleU32(this->pf.bmask);
+ this->pf.amask = POSH_LittleU32(this->pf.amask);
+ this->caps.caps1 = POSH_LittleU32(this->caps.caps1);
+ this->caps.caps2 = POSH_LittleU32(this->caps.caps2);
+ this->caps.caps3 = POSH_LittleU32(this->caps.caps3);
+ this->caps.caps4 = POSH_LittleU32(this->caps.caps4);
+ this->notused = POSH_LittleU32(this->notused);
+
+ this->header10.dxgiFormat = POSH_LittleU32(this->header10.dxgiFormat);
+ this->header10.resourceDimension = POSH_LittleU32(this->header10.resourceDimension);
+ this->header10.miscFlag = POSH_LittleU32(this->header10.miscFlag);
+ this->header10.arraySize = POSH_LittleU32(this->header10.arraySize);
+ this->header10.reserved = POSH_LittleU32(this->header10.reserved);
+}
+*/
+
bool DDSHeader::hasDX10Header() const
{
- return this->pf.fourcc == FOURCC_DX10; // @@ This is according to AMD
- //return this->pf.flags == 0; // @@ This is according to MS
+ return this->pf.fourcc == FOURCC_DX10;
+}
+
+uint DDSHeader::signature() const
+{
+ return this->reserved[9];
+}
+
+uint DDSHeader::toolVersion() const
+{
+ return this->reserved[10];
+}
+
+uint DDSHeader::userVersion() const
+{
+ if (this->reserved[7] == FOURCC_UVER) {
+ return this->reserved[8];
+ }
+ return 0;
+}
+
+bool DDSHeader::isNormalMap() const
+{
+ return (pf.flags & DDPF_NORMAL) != 0;
+}
+
+bool DDSHeader::isSrgb() const
+{
+ return (pf.flags & DDPF_SRGB) != 0;
+}
+
+bool DDSHeader::hasAlpha() const
+{
+ return (pf.flags & DDPF_ALPHAPIXELS) != 0;
+}
+
+uint DDSHeader::d3d9Format() const
+{
+ if (pf.flags & DDPF_FOURCC) {
+ return pf.fourcc;
+ }
+ else {
+ return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask);
+ }
}
DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header()
@@ -725,6 +923,16 @@ bool DirectDrawSurface::isSupported() const
{
if (header.hasDX10Header())
{
+ if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
+ header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
+ header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM ||
+ header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM ||
+ header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM)
+ {
+ return true;
+ }
+
+ return false;
}
else
{
@@ -743,9 +951,9 @@ bool DirectDrawSurface::isSupported() const
return false;
}
}
- else if (header.pf.flags & DDPF_RGB)
- {
- // All RGB formats are supported now.
+ else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE))
+ {
+ // All RGB and luminance formats are supported now.
}
else
{
@@ -768,6 +976,41 @@ bool DirectDrawSurface::isSupported() const
return true;
}
+bool DirectDrawSurface::hasAlpha() const
+{
+ if (header.hasDX10Header())
+ {
+ /* TODO: Update hasAlpha to handle all DX10 formats. */
+ return
+ header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
+ header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
+ header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM;
+ }
+ else
+ {
+ if (header.pf.flags & DDPF_RGB)
+ {
+ return header.pf.amask != 0;
+ }
+ else if (header.pf.flags & DDPF_FOURCC)
+ {
+ if (header.pf.fourcc == FOURCC_RXGB ||
+ header.pf.fourcc == FOURCC_ATI1 ||
+ header.pf.fourcc == FOURCC_ATI2 ||
+ header.pf.flags & DDPF_NORMAL)
+ {
+ return false;
+ }
+ else
+ {
+ // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?)
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
uint DirectDrawSurface::mipmapCount() const
{
@@ -794,22 +1037,6 @@ uint DirectDrawSurface::depth() const
else return 1;
}
-bool DirectDrawSurface::hasAlpha() const
-{
- if ((header.pf.flags & DDPF_RGB) && (header.pf.amask == 0))
- {
- return false;
- }
- else if (header.pf.fourcc == FOURCC_DXT1)
- {
- return false;
- }
- else
- {
- return true;
- }
-}
-
bool DirectDrawSurface::isTexture1D() const
{
if (header.hasDX10Header())
@@ -853,6 +1080,16 @@ void DirectDrawSurface::setNormalFlag(bool b)
header.setNormalFlag(b);
}
+void DirectDrawSurface::setHasAlphaFlag(bool b)
+{
+ header.setHasAlphaFlag(b);
+}
+
+void DirectDrawSurface::setUserVersion(int version)
+{
+ header.setUserVersion(version);
+}
+
void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
{
stream.seek(offset(face, mipmap));
@@ -869,14 +1106,31 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
img->allocate(w, h);
- if (header.pf.flags & DDPF_RGB)
+ if (hasAlpha())
+ {
+ img->setFormat(Image::Format_ARGB);
+ }
+ else
{
- readLinearImage(img);
+ img->setFormat(Image::Format_RGB);
}
- else if (header.pf.flags & DDPF_FOURCC)
+
+ if (header.hasDX10Header())
{
+ // So far only block formats supported.
readBlockImage(img);
}
+ else
+ {
+ if (header.pf.flags & DDPF_RGB)
+ {
+ readLinearImage(img);
+ }
+ else if (header.pf.flags & DDPF_FOURCC)
+ {
+ readBlockImage(img);
+ }
+ }
}
void DirectDrawSurface::readLinearImage(Image * img)
@@ -906,17 +1160,6 @@ void DirectDrawSurface::readLinearImage(Image * img)
return;
}
- // set image format: RGB or ARGB
- // alpha channel exists if and only if the alpha mask is non-zero
- if (header.pf.amask == 0)
- {
- img->setFormat(Image::Format_RGB);
- }
- else
- {
- img->setFormat(Image::Format_ARGB);
- }
-
// Read linear RGB images.
for (uint y = 0; y < h; y++)
{
@@ -926,10 +1169,10 @@ void DirectDrawSurface::readLinearImage(Image * img)
mem_read(stream, (unsigned char *)(&c), byteCount);
Color32 pixel(0, 0, 0, 0xFF);
- pixel.r = PixelFormat::convert(c >> rshift, rsize, 8);
- pixel.g = PixelFormat::convert(c >> gshift, gsize, 8);
- pixel.b = PixelFormat::convert(c >> bshift, bsize, 8);
- pixel.a = PixelFormat::convert(c >> ashift, asize, 8);
+ pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8);
+ pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8);
+ pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8);
+ pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8);
img->pixel(x, y) = pixel;
}
@@ -939,19 +1182,6 @@ void DirectDrawSurface::readLinearImage(Image * img)
void DirectDrawSurface::readBlockImage(Image * img)
{
- // set image format: RGB or ARGB
- if (header.pf.fourcc == FOURCC_RXGB ||
- header.pf.fourcc == FOURCC_ATI1 ||
- header.pf.fourcc == FOURCC_ATI2 ||
- header.pf.flags & DDPF_NORMAL)
- {
- img->setFormat(Image::Format_RGB);
- }
- else
- {
- img->setFormat(Image::Format_ARGB);
- }
-
const uint w = img->width();
const uint h = img->height();
@@ -993,20 +1223,33 @@ static Color32 buildNormal(uint8 x, uint8 y)
void DirectDrawSurface::readBlock(ColorBlock * rgba)
{
- if (header.pf.fourcc == FOURCC_DXT1)
+ uint fourcc = header.pf.fourcc;
+
+ // Map DX10 block formats to fourcc codes.
+ if (header.hasDX10Header())
+ {
+ if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM) fourcc = FOURCC_DXT1;
+ if (header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM) fourcc = FOURCC_DXT3;
+ if (header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM) fourcc = FOURCC_DXT5;
+ if (header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM) fourcc = FOURCC_ATI1;
+ if (header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) fourcc = FOURCC_ATI2;
+ }
+
+
+ if (fourcc == FOURCC_DXT1)
{
BlockDXT1 block;
mem_read(stream, block);
block.decodeBlock(rgba);
}
- else if (header.pf.fourcc == FOURCC_DXT2 ||
+ else if (fourcc == FOURCC_DXT2 ||
header.pf.fourcc == FOURCC_DXT3)
{
BlockDXT3 block;
mem_read(stream, block);
block.decodeBlock(rgba);
}
- else if (header.pf.fourcc == FOURCC_DXT4 ||
+ else if (fourcc == FOURCC_DXT4 ||
header.pf.fourcc == FOURCC_DXT5 ||
header.pf.fourcc == FOURCC_RXGB)
{
@@ -1014,7 +1257,7 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
mem_read(stream, block);
block.decodeBlock(rgba);
- if (header.pf.fourcc == FOURCC_RXGB)
+ if (fourcc == FOURCC_RXGB)
{
// Swap R & A.
for (int i = 0; i < 16; i++)
@@ -1026,13 +1269,13 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
}
}
}
- else if (header.pf.fourcc == FOURCC_ATI1)
+ else if (fourcc == FOURCC_ATI1)
{
BlockATI1 block;
mem_read(stream, block);
block.decodeBlock(rgba);
}
- else if (header.pf.fourcc == FOURCC_ATI2)
+ else if (fourcc == FOURCC_ATI2)
{
BlockATI2 block;
mem_read(stream, block);
@@ -1042,7 +1285,7 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
// If normal flag set, convert to normal.
if (header.pf.flags & DDPF_NORMAL)
{
- if (header.pf.fourcc == FOURCC_ATI2)
+ if (fourcc == FOURCC_ATI2)
{
for (int i = 0; i < 16; i++)
{
@@ -1050,7 +1293,7 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
c = buildNormal(c.r, c.g);
}
}
- else if (header.pf.fourcc == FOURCC_DXT5)
+ else if (fourcc == FOURCC_DXT5)
{
for (int i = 0; i < 16; i++)
{
@@ -1076,6 +1319,27 @@ uint DirectDrawSurface::blockSize() const
case FOURCC_RXGB:
case FOURCC_ATI2:
return 16;
+ case FOURCC_DX10:
+ switch(header.header10.dxgiFormat)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ return 8;
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ return 16;
+ };
};
// Not a block image.
@@ -1102,14 +1366,10 @@ uint DirectDrawSurface::mipmapSize(uint mipmap) const
h = (h + 3) / 4;
return blockSize() * w * h;
}
- else if (header.pf.flags & DDPF_RGB)
+ else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE))
{
- // Align pixels to bytes.
- uint byteCount = (header.pf.bitcount + 7) / 8;
-
- // Align pitch to 4 bytes.
- uint pitch = 4 * ((w * byteCount + 3) / 4);
-
+ uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects.
+
return pitch * h * d;
}
else {
@@ -1133,7 +1393,7 @@ uint DirectDrawSurface::faceSize() const
uint DirectDrawSurface::offset(const uint face, const uint mipmap)
{
- uint size = 128; //sizeof(DDSHeader);
+ uint size = 128; // sizeof(DDSHeader);
if (header.hasDX10Header())
{
@@ -1156,7 +1416,6 @@ uint DirectDrawSurface::offset(const uint face, const uint mipmap)
void DirectDrawSurface::printInfo() const
{
- /* printf("FOURCC: %c%c%c%c\n", ((unsigned char *)&header.fourcc)[0], ((unsigned char *)&header.fourcc)[1], ((unsigned char *)&header.fourcc)[2], ((unsigned char *)&header.fourcc)[3]); */
printf("Flags: 0x%.8X\n", header.flags);
if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
@@ -1175,9 +1434,9 @@ void DirectDrawSurface::printInfo() const
printf("Mipmap count: %d\n", header.mipmapcount);
printf("Pixel Format:\n");
- /* printf("\tSize: %d\n", header.pf.size); */
printf("\tFlags: 0x%.8X\n", header.pf.flags);
if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
+ if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n");
if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
@@ -1188,23 +1447,30 @@ void DirectDrawSurface::printInfo() const
if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
- printf("\tFourCC: '%c%c%c%c'\n",
- ((header.pf.fourcc >> 0) & 0xFF),
- ((header.pf.fourcc >> 8) & 0xFF),
- ((header.pf.fourcc >> 16) & 0xFF),
- ((header.pf.fourcc >> 24) & 0xFF));
- if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0))
+ if (header.pf.fourcc != 0) {
+ // Display fourcc code even when DDPF_FOURCC flag not set.
+ printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n",
+ ((header.pf.fourcc >> 0) & 0xFF),
+ ((header.pf.fourcc >> 8) & 0xFF),
+ ((header.pf.fourcc >> 16) & 0xFF),
+ ((header.pf.fourcc >> 24) & 0xFF),
+ header.pf.fourcc);
+ }
+
+ if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0))
{
- printf("\tSwizzle: '%c%c%c%c'\n",
+ printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n",
(header.pf.bitcount >> 0) & 0xFF,
(header.pf.bitcount >> 8) & 0xFF,
(header.pf.bitcount >> 16) & 0xFF,
- (header.pf.bitcount >> 24) & 0xFF);
+ (header.pf.bitcount >> 24) & 0xFF,
+ header.pf.bitcount);
}
else
{
printf("\tBit count: %d\n", header.pf.bitcount);
}
+
printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
@@ -1244,7 +1510,7 @@ void DirectDrawSurface::printInfo() const
printf("\tArray size: %u\n", header.header10.arraySize);
}
- if (header.reserved[9] == MAKEFOURCC('N', 'V', 'T', 'T'))
+ if (header.reserved[9] == FOURCC_NVTT)
{
int major = (header.reserved[10] >> 16) & 0xFF;
int minor = (header.reserved[10] >> 8) & 0xFF;
@@ -1253,5 +1519,10 @@ void DirectDrawSurface::printInfo() const
printf("Version:\n");
printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
}
+
+ if (header.reserved[7] == FOURCC_UVER)
+ {
+ printf("User Version: %d\n", header.reserved[8]);
+ }
}
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
index cc04c50e795..5978e780991 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -126,11 +126,25 @@ struct DDSHeader
void setLinearSize(uint size);
void setPitch(uint pitch);
void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
+ void setFormatCode(uint code);
+ void setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
void setDX10Format(uint format);
void setNormalFlag(bool b);
+ void setSrgbFlag(bool b);
+ void setHasAlphaFlag(bool b);
+ void setUserVersion(int version);
+
+ /*void swapBytes();*/
bool hasDX10Header() const;
+ uint signature() const;
+ uint toolVersion() const;
+ uint userVersion() const;
+ bool isNormalMap() const;
+ bool isSrgb() const;
+ bool hasAlpha() const;
+ uint d3d9Format() const;
};
/// DirectDraw Surface. (DDS)
@@ -142,6 +156,8 @@ public:
bool isValid() const;
bool isSupported() const;
+
+ bool hasAlpha() const;
uint mipmapCount() const;
uint width() const;
@@ -153,8 +169,8 @@ public:
bool isTextureCube() const;
void setNormalFlag(bool b);
-
- bool hasAlpha() const; /* false for DXT1, true for all other DXTs */
+ void setHasAlphaFlag(bool b);
+ void setUserVersion(int version);
void mipmap(Image * img, uint f, uint m);
// void mipmap(FloatImage * img, uint f, uint m);
diff --git a/source/blender/imbuf/intern/dds/Image.cpp b/source/blender/imbuf/intern/dds/Image.cpp
index a775a9125d2..b9ec1c0c3aa 100644
--- a/source/blender/imbuf/intern/dds/Image.cpp
+++ b/source/blender/imbuf/intern/dds/Image.cpp
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -41,7 +41,7 @@
#include <stdio.h> // printf
-Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(0)
+Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL)
{
}
@@ -61,7 +61,7 @@ void Image::allocate(uint w, uint h)
void Image::free()
{
if (m_data) delete [] m_data;
- m_data = 0;
+ m_data = NULL;
}
@@ -132,3 +132,4 @@ void Image::setFormat(Image::Format f)
m_format = f;
}
+
diff --git a/source/blender/imbuf/intern/dds/Image.h b/source/blender/imbuf/intern/dds/Image.h
index 88051410056..96e455fc75b 100644
--- a/source/blender/imbuf/intern/dds/Image.h
+++ b/source/blender/imbuf/intern/dds/Image.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
diff --git a/source/blender/imbuf/intern/dds/PixelFormat.h b/source/blender/imbuf/intern/dds/PixelFormat.h
index c483c525570..35c6eacb972 100644
--- a/source/blender/imbuf/intern/dds/PixelFormat.h
+++ b/source/blender/imbuf/intern/dds/PixelFormat.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -107,6 +107,38 @@
}
}
+ inline float quantizeCeil(float f, int inbits, int outbits)
+ {
+ //uint i = f * (float(1 << inbits) - 1);
+ //i = convert(i, inbits, outbits);
+ //float result = float(i) / (float(1 << outbits) - 1);
+ //nvCheck(result >= f);
+ float result;
+ int offset = 0;
+ do {
+ uint i = offset + uint(f * (float(1 << inbits) - 1));
+ i = convert(i, inbits, outbits);
+ result = float(i) / (float(1 << outbits) - 1);
+ offset++;
+ } while (result < f);
+
+ return result;
+ }
+
+ /*
+ inline float quantizeRound(float f, int bits)
+ {
+ float scale = float(1 << bits);
+ return fround(f * scale) / scale;
+ }
+
+ inline float quantizeFloor(float f, int bits)
+ {
+ float scale = float(1 << bits);
+ return floor(f * scale) / scale;
+ }
+ */
+
} // PixelFormat namespace
#endif // _DDS_IMAGE_PIXELFORMAT_H
diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp
index 88c5277e097..497109efd25 100644
--- a/source/blender/imbuf/intern/dds/Stream.cpp
+++ b/source/blender/imbuf/intern/dds/Stream.cpp
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h
index acc2c8bb176..ca081d331fe 100644
--- a/source/blender/imbuf/intern/dds/Stream.h
+++ b/source/blender/imbuf/intern/dds/Stream.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index a7b2934cafa..73ee3a2cb9c 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -106,10 +106,21 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags)
}
/* convert DDS into ImBuf */
- // TODO use the image RGB or RGBA tag to determine the bits per pixel
- if (dds.hasAlpha()) bits_per_pixel = 32;
- else bits_per_pixel = 24;
- ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0);
+ dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
+ pixels = img.pixels();
+ numpixels = dds.width() * dds.height();
+ bits_per_pixel = 24;
+ if (img.format() == Image::Format_ARGB) {
+ /* check that there is effectively an alpha channel */
+ for (unsigned int i = 0; i < numpixels; i++) {
+ pixel = pixels[i];
+ if (pixel.a != 255) {
+ bits_per_pixel = 32;
+ break;
+ };
+ };
+ };
+ ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0);
if (ibuf == 0) return(0); /* memory allocation failed */
ibuf->ftype = DDS;
@@ -120,9 +131,6 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags)
if (ibuf->rect == 0) return(ibuf);
rect = ibuf->rect;
- dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
- pixels = img.pixels();
- numpixels = dds.width() * dds.height();
cp[3] = 0xff; /* default alpha if alpha channel is not present */
for (unsigned int i = 0; i < numpixels; i++) {
diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h
index cfc6910e71d..d78e4f31474 100644
--- a/source/blender/imbuf/intern/dds/dds_api.h
+++ b/source/blender/imbuf/intern/dds/dds_api.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributors: Amorilia (amorilia@gamebox.net)
+ * Contributors: Amorilia (amorilia@users.sourceforge.net)
*
* ***** END GPL LICENSE BLOCK *****
*/