diff options
author | José Fonseca <jfonseca@vmware.com> | 2013-06-06 14:11:27 +0100 |
---|---|---|
committer | José Fonseca <jfonseca@vmware.com> | 2013-06-06 14:11:27 +0100 |
commit | d40bc73f268480b94cd70dbdc1fa67aa82666882 (patch) | |
tree | b59f0f38ee02018bd9b3b43c084e0584ee254a58 | |
parent | 87831e9094bf0f41b366dbbc502f481856c045ba (diff) |
tools: Add simple DDS viewer.
From http://tfc.duke.free.fr/ . Quite handy to visualize compressed
textures, which are often stored in DDS format.
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/tools/.gitignore | 1 | ||||
-rw-r--r-- | src/tools/CMakeLists.txt | 30 | ||||
-rw-r--r-- | src/tools/dds.c | 395 |
4 files changed, 427 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 13da6b62..4e1c54ee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ add_subdirectory (vp) add_subdirectory (vpglsl) add_subdirectory (gs) add_subdirectory (slang) +add_subdirectory (tools) if (EGL_FOUND) add_subdirectory(egl) diff --git a/src/tools/.gitignore b/src/tools/.gitignore new file mode 100644 index 00000000..d7985d04 --- /dev/null +++ b/src/tools/.gitignore @@ -0,0 +1 @@ +dds diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt new file mode 100644 index 00000000..dbf7c4f6 --- /dev/null +++ b/src/tools/CMakeLists.txt @@ -0,0 +1,30 @@ +include_directories ( + ${CMAKE_SOURCE_DIR}/src/util + ${OPENGL_INCLUDE_PATH} + ${GLUT_INCLUDE_DIR} + ${GLEW_INCLUDE_DIR} +) + +link_directories ( + ${CMAKE_SOURCE_DIR}/src/util +) + +link_libraries ( + util + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${GLUT_glut_LIBRARY} + ${GLEW_glew_LIBRARY} +) + +set (subdir tools) + +set (targets + dds +) + +foreach (target ${targets}) + add_executable (${subdir}_${target} ${target}.c) + set_target_properties (${subdir}_${target} PROPERTIES OUTPUT_NAME ${target}) + install (TARGETS ${subdir}_${target} DESTINATION ${subdir}) +endforeach (target) diff --git a/src/tools/dds.c b/src/tools/dds.c new file mode 100644 index 00000000..78aa1d78 --- /dev/null +++ b/src/tools/dds.c @@ -0,0 +1,395 @@ +/* + * dds.c -- dds texture loader + * last modification: aug. 14, 2007 + * + * Copyright (c) 2005-2007 David HENRY + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * gcc -Wall -ansi -lGL -lGLU -lglut dds.c -o dds + */ + +#ifndef _WIN32 +#ifndef GL_GLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES 1 +#endif /* GL_GLEXT_PROTOTYPES */ +#endif /* _WIN32 */ + +#include <GL/glut.h> +#include <GL/glext.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef _WIN32 +PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2D = NULL; +#endif /* _WIN32 */ + + +/* OpenGL texture info */ +struct gl_texture_t +{ + GLsizei width; + GLsizei height; + + GLenum format; + GLint internalFormat; + GLuint id; + + GLubyte *texels; + + GLint numMipmaps; +}; + +/* DirectDraw's structures */ +struct DDPixelFormat +{ + GLuint size; + GLuint flags; + GLuint fourCC; + GLuint bpp; + GLuint redMask; + GLuint greenMask; + GLuint blueMask; + GLuint alphaMask; +}; + +struct DDSCaps +{ + GLuint caps; + GLuint caps2; + GLuint caps3; + GLuint caps4; +}; + +struct DDColorKey +{ + GLuint lowVal; + GLuint highVal; +}; + +struct DDSurfaceDesc +{ + GLuint size; + GLuint flags; + GLuint height; + GLuint width; + GLuint pitch; + GLuint depth; + GLuint mipMapLevels; + GLuint alphaBitDepth; + GLuint reserved; + GLuint surface; + + struct DDColorKey ckDestOverlay; + struct DDColorKey ckDestBlt; + struct DDColorKey ckSrcOverlay; + struct DDColorKey ckSrcBlt; + + struct DDPixelFormat format; + struct DDSCaps caps; + + GLuint textureStage; +}; + +#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + (GLuint)( \ + (((GLuint)(GLubyte)(ch3) << 24) & 0xFF000000) | \ + (((GLuint)(GLubyte)(ch2) << 16) & 0x00FF0000) | \ + (((GLuint)(GLubyte)(ch1) << 8) & 0x0000FF00) | \ + ((GLuint)(GLubyte)(ch0) & 0x000000FF) ) + +#define FOURCC_DXT1 MAKEFOURCC('D', 'X', 'T', '1') +#define FOURCC_DXT3 MAKEFOURCC('D', 'X', 'T', '3') +#define FOURCC_DXT5 MAKEFOURCC('D', 'X', 'T', '5') + +/* texture Id */ +GLuint texId; + + +#ifndef max +static int +max (int a, int b) +{ + return ((a > b) ? a : b); +} +#endif + +static struct gl_texture_t * +ReadDDSFile (const char *filename) +{ + struct DDSurfaceDesc ddsd; + struct gl_texture_t *texinfo; + FILE *fp; + char magic[4]; + int mipmapFactor; + long bufferSize, curr, end; + + /* Open the file */ + fp = fopen (filename, "rb"); + if (!fp) + { + fprintf (stderr, "error: couldn't open \"%s\"!\n", filename); + return NULL; + } + + /* Read magic number and check if valid .dds file */ + fread (&magic, sizeof (char), 4, fp); + + if (strncmp (magic, "DDS ", 4) != 0) + { + fprintf (stderr, "the file \"%s\" doesn't appear to be" + "a valid .dds file!\n", filename); + fclose (fp); + return NULL; + } + + /* Get the surface descriptor */ + fread (&ddsd, sizeof (ddsd), 1, fp); + + texinfo = (struct gl_texture_t *) + calloc (sizeof (struct gl_texture_t), 1); + texinfo->width = ddsd.width; + texinfo->height = ddsd.height; + texinfo->numMipmaps = ddsd.mipMapLevels; + + switch (ddsd.format.fourCC) + { + case FOURCC_DXT1: + /* DXT1's compression ratio is 8:1 */ + texinfo->format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + texinfo->internalFormat = 3; + mipmapFactor = 2; + break; + + case FOURCC_DXT3: + /* DXT3's compression ratio is 4:1 */ + texinfo->format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + texinfo->internalFormat = 4; + mipmapFactor = 4; + break; + + case FOURCC_DXT5: + /* DXT5's compression ratio is 4:1 */ + texinfo->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + texinfo->internalFormat = 4; + mipmapFactor = 4; + break; + + default: + /* Bad fourCC, unsupported or bad format */ + fprintf (stderr, "the file \"%s\" doesn't appear to be" + "compressed using DXT1, DXT3, or DXT5! [%i]\n", + filename, ddsd.format.fourCC); + free (texinfo); + fclose (fp); + return NULL; + } + + /* Calculate pixel data size */ + curr = ftell (fp); + fseek (fp, 0, SEEK_END); + end = ftell (fp); + fseek (fp, curr, SEEK_SET); + bufferSize = end - curr; + + /* Read pixel data with mipmaps */ + texinfo->texels = (GLubyte *)malloc (bufferSize * sizeof (GLubyte)); + fread (texinfo->texels, sizeof (GLubyte), bufferSize, fp); + + /* Close the file */ + fclose (fp); + return texinfo; +} + +GLuint +loadDDSTexture (const char *filename) +{ + struct gl_texture_t *compressed_texture = NULL; + GLsizei mipWidth, mipHeight, mipSize; + int blockSize, offset; + GLuint tex_id = 0; + GLint mip; + + /* Read texture from file */ + compressed_texture = ReadDDSFile (filename); + + if (compressed_texture && compressed_texture->texels) + { + /* Generate new texture */ + glGenTextures (1, &compressed_texture->id); + glBindTexture (GL_TEXTURE_2D, compressed_texture->id); + + /* Setup some parameters for texture filters and mipmapping */ + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + mipWidth = compressed_texture->width; + mipHeight = compressed_texture->height; + blockSize = (compressed_texture->format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16; + offset = 0; + + /* Upload mipmaps to video memory */ + for (mip = 0; mip < compressed_texture->numMipmaps; ++mip) + { + mipSize = ((mipWidth + 3) / 4) * ((mipHeight + 3) / 4) * blockSize; + + glCompressedTexImage2D (GL_TEXTURE_2D, mip, compressed_texture->format, + mipWidth, mipHeight, 0, mipSize, + compressed_texture->texels + offset); + + mipWidth = max (mipWidth >> 1, 1); + mipHeight = max (mipHeight >> 1, 1); + + offset += mipSize; + } + + tex_id = compressed_texture->id; + + /* Opengl has its own copy of pixels */ + free (compressed_texture->texels); + free (compressed_texture); + } + + return tex_id; +} + +static void +cleanup () +{ + glDeleteTextures (1, &texId); +} + +static void +init (const char *filename) +{ + const char *glexts = (const char *)glGetString (GL_EXTENSIONS); + + /* Initialize OpenGL */ + glClearColor (0.5f, 0.5f, 0.5f, 1.0f); + glShadeModel (GL_SMOOTH); + + glEnable (GL_DEPTH_TEST); + + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* Check for S3TC support */ + if (!strstr (glexts, "GL_EXT_texture_compression_s3tc")) + { + fprintf (stderr, "error: GL_EXT_texture_compression_s3tc " + "extension is required for DDS textures!\n"); + exit(-1); + } + + /* Initialize OpenGL extensions */ +#ifdef _WIN32 + glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) + wglGetProcAddress ("glCompressedTexImage2DARB"); +#endif + + /* Load DDS texture from file */ + texId = loadDDSTexture (filename); + if (!texId) + exit (EXIT_FAILURE); +} + +static void +reshape (int w, int h) +{ + if (h == 0) + h = 1; + + glViewport (0, 0, (GLsizei)w, (GLsizei)h); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective (45.0, w/(GLdouble)h, 0.1, 1000.0); + + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + glutPostRedisplay (); +} + +static void +display () +{ + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity (); + + glEnable (GL_TEXTURE_2D); + glBindTexture (GL_TEXTURE_2D, texId); + + /* Draw textured quad */ + glTranslatef (0.0, 0.0, -5.0); + glBegin (GL_QUADS); + glTexCoord2f (0.0f, 0.0f); + glVertex3f (-1.0f, -1.0f, 0.0f); + + glTexCoord2f (1.0f, 0.0f); + glVertex3f (1.0f, -1.0f, 0.0f); + + glTexCoord2f (1.0f, 1.0f); + glVertex3f (1.0f, 1.0f, 0.0f); + + glTexCoord2f (0.0f, 1.0f); + glVertex3f (-1.0f, 1.0f, 0.0f); + glEnd (); + + glDisable (GL_TEXTURE_2D); + + glutSwapBuffers (); +} + +static void +keyboard (unsigned char key, int x, int y) +{ + /* Escape */ + if (key == 27) + exit (0); +} + +int +main (int argc, char *argv[]) +{ + if (argc < 2) + { + fprintf (stderr, "usage: %s <filename.dds>\n", argv[0]); + return -1; + } + + glutInit (&argc, argv); + glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); + glutInitWindowSize (640, 480); + glutCreateWindow ("DDS Texture Demo"); + + atexit (cleanup); + init (argv[1]); + + glutReshapeFunc (reshape); + glutDisplayFunc (display); + glutKeyboardFunc (keyboard); + + glutMainLoop (); + + return 0; +} |