[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51620] trunk/blender/source/blender: Better fix for #32837: DDS compressed textures now no longer need to be flipped

Brecht Van Lommel brechtvanlommel at pandora.be
Thu Oct 25 14:54:17 CEST 2012


Revision: 51620
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51620
Author:   blendix
Date:     2012-10-25 12:54:16 +0000 (Thu, 25 Oct 2012)
Log Message:
-----------
Better fix for #32837: DDS compressed textures now no longer need to be flipped
when saving, rather we flip the compressed texture during load. The code used
here comes from the chromium O3D project:
http://src.chromium.org/chrome/trunk/o3d/core/cross/bitmap_dds.cc

Also made it only load compressed for power-of-two resolution images, it doesn't
seem to work for other resolutions, just falls back to non-compressed then.

Modified Paths:
--------------
    trunk/blender/source/blender/gpu/intern/gpu_draw.c
    trunk/blender/source/blender/imbuf/intern/dds/CMakeLists.txt
    trunk/blender/source/blender/imbuf/intern/dds/SConscript
    trunk/blender/source/blender/imbuf/intern/dds/dds_api.cpp

Added Paths:
-----------
    trunk/blender/source/blender/imbuf/intern/dds/FlipDXT.cpp
    trunk/blender/source/blender/imbuf/intern/dds/FlipDXT.h

Modified: trunk/blender/source/blender/gpu/intern/gpu_draw.c
===================================================================
--- trunk/blender/source/blender/gpu/intern/gpu_draw.c	2012-10-25 12:53:27 UTC (rev 51619)
+++ trunk/blender/source/blender/gpu/intern/gpu_draw.c	2012-10-25 12:54:16 UTC (rev 51620)
@@ -730,12 +730,17 @@
 		return FALSE;
 	}
 
+	if(!is_power_of_2_i(width) || !is_power_of_2_i(height)) {
+		printf("Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
+		return FALSE;
+	}
+
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
 
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
-	blocksize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
+	blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
 	for (i=0; i<ibuf->dds_data.nummipmaps && (width||height); ++i) {
 		if (width == 0)
 			width = 1;

Modified: trunk/blender/source/blender/imbuf/intern/dds/CMakeLists.txt
===================================================================
--- trunk/blender/source/blender/imbuf/intern/dds/CMakeLists.txt	2012-10-25 12:53:27 UTC (rev 51619)
+++ trunk/blender/source/blender/imbuf/intern/dds/CMakeLists.txt	2012-10-25 12:54:16 UTC (rev 51620)
@@ -40,6 +40,7 @@
 
 set(SRC
 	BlockDXT.cpp
+	FlipDXT.cpp
 	ColorBlock.cpp
 	DirectDrawSurface.cpp
 	Image.cpp

Added: trunk/blender/source/blender/imbuf/intern/dds/FlipDXT.cpp
===================================================================
--- trunk/blender/source/blender/imbuf/intern/dds/FlipDXT.cpp	                        (rev 0)
+++ trunk/blender/source/blender/imbuf/intern/dds/FlipDXT.cpp	2012-10-25 12:54:16 UTC (rev 51620)
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This file comes from the chromium project, adapted to Blender to add DDS
+// flipping to OpenGL convention for Blender
+
+#include "IMB_imbuf_types.h"
+
+#include <string.h>
+
+#include <Common.h>
+#include <Stream.h>
+#include <ColorBlock.h>
+#include <BlockDXT.h>
+#include <FlipDXT.h>
+
+// A function that flips a DXTC block.
+typedef void (*FlipBlockFunction)(uint8_t *block);
+
+// Flips a full DXT1 block in the y direction.
+static void FlipDXT1BlockFull(uint8_t *block)
+{
+	// A DXT1 block layout is:
+	// [0-1] color0.
+	// [2-3] color1.
+	// [4-7] color bitmap, 2 bits per pixel.
+	// So each of the 4-7 bytes represents one line, flipping a block is just
+	// flipping those bytes.
+	uint8_t tmp = block[4];
+	block[4] = block[7];
+	block[7] = tmp;
+	tmp = block[5];
+	block[5] = block[6];
+	block[6] = tmp;
+}
+
+// Flips the first 2 lines of a DXT1 block in the y direction.
+static void FlipDXT1BlockHalf(uint8_t *block)
+{
+	// See layout above.
+	uint8_t tmp = block[4];
+	block[4] = block[5];
+	block[5] = tmp;
+}
+
+// Flips a full DXT3 block in the y direction.
+static void FlipDXT3BlockFull(uint8_t *block)
+{
+	// A DXT3 block layout is:
+	// [0-7]	alpha bitmap, 4 bits per pixel.
+	// [8-15] a DXT1 block.
+
+	// We can flip the alpha bits at the byte level (2 bytes per line).
+	uint8_t tmp = block[0];
+
+	block[0] = block[6];
+	block[6] = tmp;
+	tmp = block[1];
+	block[1] = block[7];
+	block[7] = tmp;
+	tmp = block[2];
+	block[2] = block[4];
+	block[4] = tmp;
+	tmp = block[3];
+	block[3] = block[5];
+	block[5] = tmp;
+
+	// And flip the DXT1 block using the above function.
+	FlipDXT1BlockFull(block + 8);
+}
+
+// Flips the first 2 lines of a DXT3 block in the y direction.
+static void FlipDXT3BlockHalf(uint8_t *block)
+{
+	// See layout above.
+	uint8_t tmp = block[0];
+
+	block[0] = block[2];
+	block[2] = tmp;
+	tmp = block[1];
+	block[1] = block[3];
+	block[3] = tmp;
+	FlipDXT1BlockHalf(block + 8);
+}
+
+// Flips a full DXT5 block in the y direction.
+static void FlipDXT5BlockFull(uint8_t *block)
+{
+	// A DXT5 block layout is:
+	// [0]		alpha0.
+	// [1]		alpha1.
+	// [2-7]	alpha bitmap, 3 bits per pixel.
+	// [8-15] a DXT1 block.
+
+	// The alpha bitmap doesn't easily map lines to bytes, so we have to
+	// interpret it correctly.	Extracted from
+	// http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt :
+	//
+	//	 The 6 "bits" bytes of the block are decoded into one 48-bit integer:
+	//
+	//		 bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
+	//									 256 * (bits_4 + 256 * bits_5))))
+	//
+	//	 bits is a 48-bit unsigned integer, from which a three-bit control code
+	//	 is extracted for a texel at location (x,y) in the block using:
+	//
+	//			 code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
+	//
+	//	 where bit 47 is the most significant and bit 0 is the least
+	//	 significant bit.
+	unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]);
+	unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]);
+	// swap lines 0 and 1 in line_0_1.
+	unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
+			((line_0_1 & 0xfff000) >> 12);
+	// swap lines 2 and 3 in line_2_3.
+	unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) |
+			((line_2_3 & 0xfff000) >> 12);
+
+	block[2] = line_3_2 & 0xff;
+	block[3] = (line_3_2 & 0xff00) >> 8;
+	block[4] = (line_3_2 & 0xff0000) >> 8;
+	block[5] = line_1_0 & 0xff;
+	block[6] = (line_1_0 & 0xff00) >> 8;
+	block[7] = (line_1_0 & 0xff0000) >> 8;
+
+	// And flip the DXT1 block using the above function.
+	FlipDXT1BlockFull(block + 8);
+}
+
+// Flips the first 2 lines of a DXT5 block in the y direction.
+static void FlipDXT5BlockHalf(uint8_t *block)
+{
+	// See layout above.
+	unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]);
+	unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
+			((line_0_1 & 0xfff000) >> 12);
+	block[2] = line_1_0 & 0xff;
+	block[3] = (line_1_0 & 0xff00) >> 8;
+	block[4] = (line_1_0 & 0xff0000) >> 8;
+	FlipDXT1BlockHalf(block + 8);
+}
+
+// Flips a DXTC image, by flipping and swapping DXTC blocks as appropriate.
+int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data)
+{
+	// must have valid dimensions
+	if(width == 0 || height == 0)
+		return 0;
+	// height must be a power-of-two
+	if(height & (height - 1) != 0)
+		return 0;
+
+	FlipBlockFunction full_block_function;
+	FlipBlockFunction half_block_function;
+	unsigned int block_bytes = 0;
+
+	switch (fourcc) {
+		case FOURCC_DXT1:
+			full_block_function = FlipDXT1BlockFull;
+			half_block_function = FlipDXT1BlockHalf;
+			block_bytes = 8;
+			break;
+		case FOURCC_DXT3:
+			full_block_function = FlipDXT3BlockFull;
+			half_block_function = FlipDXT3BlockHalf;
+			block_bytes = 16;
+			break;
+		case FOURCC_DXT5:
+			full_block_function = FlipDXT5BlockFull;
+			half_block_function = FlipDXT5BlockHalf;
+			block_bytes = 16;
+			break;
+		default:
+			return 0;
+	}
+
+	unsigned int mip_width = width;
+	unsigned int mip_height = height;
+
+	for (unsigned int i = 0; i < levels; ++i) {
+		unsigned int blocks_per_row = (mip_width + 3) / 4;
+		unsigned int blocks_per_col = (mip_height + 3) / 4;
+		unsigned int blocks = blocks_per_row * blocks_per_col;
+
+		if (mip_height == 1) {
+			// no flip to do, and we're done.
+			break;
+		}
+		else if (mip_height == 2) {
+			// flip the first 2 lines in each block.
+			for (unsigned int i = 0; i < blocks_per_row; ++i) {
+				half_block_function(data + i * block_bytes);
+			}
+		}
+		else {
+			// flip each block.
+			for (unsigned int i = 0; i < blocks; ++i)
+				full_block_function(data + i * block_bytes);
+
+			// swap each block line in the first half of the image with the
+			// corresponding one in the second half.
+			// note that this is a no-op if mip_height is 4.
+			unsigned int row_bytes = block_bytes * blocks_per_row;
+			uint8_t *temp_line = new uint8_t[row_bytes];
+
+			for (unsigned int y = 0; y < blocks_per_col / 2; ++y) {
+				uint8_t *line1 = data + y * row_bytes;
+				uint8_t *line2 = data + (blocks_per_col - y - 1) * row_bytes;
+
+				memcpy(temp_line, line1, row_bytes);
+				memcpy(line1, line2, row_bytes);
+				memcpy(line2, temp_line, row_bytes);
+			}
+
+			delete temp_line;
+		}
+
+		// mip levels are contiguous.
+		data += block_bytes * blocks;
+		mip_width = max(1U, mip_width >> 1);
+		mip_height = max(1U, mip_height >> 1);
+	}
+
+	return 1;
+}
+

Added: trunk/blender/source/blender/imbuf/intern/dds/FlipDXT.h
===================================================================
--- trunk/blender/source/blender/imbuf/intern/dds/FlipDXT.h	                        (rev 0)
+++ trunk/blender/source/blender/imbuf/intern/dds/FlipDXT.h	2012-10-25 12:54:16 UTC (rev 51620)
@@ -0,0 +1,32 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list