Edit

kc3-lang/angle/samples/dds_to_header

Branch :

  • Show log

    Commit

  • Author : Geoff Lang
    Date : 2014-05-01 17:10:24
    Hash : 876dc724
    Message : Fix 64-bit build failures. Update the BufferStorage classes to use size_t for all sizes and offsets. BufferStorage9 now uses a std::vector to manage its memory. BUG=angle:631 Change-Id: Iea4e7b33ede59a5b9c6a1245690c4b7865096fc3 Reviewed-on: https://chromium-review.googlesource.com/197819 Reviewed-by: Nicolas Capens <nicolascapens@chromium.org> Tested-by: Geoff Lang <geofflang@chromium.org>

  • main.cpp
  • //
    // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #include <ddraw.h>
    #include <d3d9types.h>
    #include <stdio.h>
    #include <fstream>
    #include <vector>
    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <array>
    
    int main(int argc, char **argv)
    {
        std::string programName(argv[0]);
        if (argc < 4)
        {
            std::cout << "usage:\n";
            std::cout << programName << "INPUT_FILE OUTPUT_C_ARRAY_NAME OUTPUT_FILE\n";
            return -1;
        }
    
        std::string inputFile(argv[1]);
        std::string outputName(argv[2]);
        std::string outputFile(argv[3]);
        std::ifstream readFile(inputFile, std::ios::binary | std::ios::in);
    
        readFile.seekg(0, std::ios::end);
        std::streamoff fileSize = readFile.tellg();
        readFile.seekg(0, std::ios::beg);
    
        const std::size_t minSize = sizeof(DDSURFACEDESC2) + sizeof(DWORD);
        if (fileSize < minSize)
        {
            std::cout << inputFile << " is only " << fileSize << " bytes, must be at greater than " << minSize
                      << " bytes to be a correct DDS image file.\n";
            return -2;
        }
    
        DWORD magicWord;
        readFile.read(reinterpret_cast<char*>(&magicWord), sizeof(DWORD));
        if (magicWord != MAKEFOURCC('D','D','S',' '))
        {
            std::cout << "Magic word must be " << MAKEFOURCC('D','D','S',' ') << ".\n";
            return -3;
        }
    
        DDSURFACEDESC2 header;
        readFile.read(reinterpret_cast<char*>(&header), sizeof(DDSURFACEDESC2));
    
        std::string formatName;
        std::size_t blockSize = 0;
        std::size_t blockWidth = 0;
        std::size_t blockHeight = 0;
    
        if (header.ddpfPixelFormat.dwFlags & DDPF_RGB)
        {
            blockSize = header.ddpfPixelFormat.dwRGBBitCount / 8;
            blockWidth = 1;
            blockHeight = 1;
    
            if (blockSize == 4)
            {
                if (header.ddpfPixelFormat.dwRBitMask        == 0x000000FF &&
                    header.ddpfPixelFormat.dwGBitMask        == 0x0000FF00 &&
                    header.ddpfPixelFormat.dwBBitMask        == 0x00FF0000 &&
                    header.ddpfPixelFormat.dwRGBAlphaBitMask == 0xFF000000)
                {
                    formatName = "RGBA8";
                }
                else if (header.ddpfPixelFormat.dwRBitMask       == 0x000000FF &&
                        header.ddpfPixelFormat.dwGBitMask        == 0x0000FF00 &&
                        header.ddpfPixelFormat.dwBBitMask        == 0x00FF0000 &&
                        header.ddpfPixelFormat.dwRGBAlphaBitMask == 0x00000000)
                {
                    formatName = "RGBX8";
                }
                else if (header.ddpfPixelFormat.dwRBitMask       == 0x000003FF &&
                        header.ddpfPixelFormat.dwGBitMask        == 0x000FFC00 &&
                        header.ddpfPixelFormat.dwBBitMask        == 0x3FF00000 &&
                        header.ddpfPixelFormat.dwRGBAlphaBitMask == 0xC0000000)
                {
                    formatName = "RGB10A2";
                }
                else if (header.ddpfPixelFormat.dwRBitMask       == 0x0000FFFF &&
                        header.ddpfPixelFormat.dwGBitMask        == 0xFFFF0000 &&
                        header.ddpfPixelFormat.dwBBitMask        == 0x00000000 &&
                        header.ddpfPixelFormat.dwRGBAlphaBitMask == 0x00000000)
                {
                    formatName = "RG16";
                }
                else if (header.ddpfPixelFormat.dwRBitMask       == 0xFFFFFFFF &&
                        header.ddpfPixelFormat.dwGBitMask        == 0x00000000 &&
                        header.ddpfPixelFormat.dwBBitMask        == 0x00000000 &&
                        header.ddpfPixelFormat.dwRGBAlphaBitMask == 0x00000000)
                {
                    formatName = "R32";
                }
                else
                {
                    formatName = "UKNOWN";
                }
            }
        }
        else if (header.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
        {
            switch (header.ddpfPixelFormat.dwFourCC)
            {
              case MAKEFOURCC('D','X','T','1'):
                formatName = "DXT1";
                blockSize = 8;
                blockWidth = 4;
                blockHeight = 4;
                break;
    
              case MAKEFOURCC('D','X','T','3'):
                formatName = "DXT3";
                blockSize = 16;
                blockWidth = 4;
                blockHeight = 4;
                break;
    
              case MAKEFOURCC('D','X','T','5'):
                formatName = "DXT5";
                blockSize = 16;
                blockWidth = 4;
                blockHeight = 4;
                break;
    
              case D3DFMT_R32F:
                formatName = "R32F";
                blockSize = 4;
                blockWidth = 1;
                blockHeight = 1;
    
              case D3DFMT_G32R32F:
                formatName = "RG32F";
                blockSize = 8;
                blockWidth = 1;
                blockHeight = 1;
    
              case D3DFMT_A32B32G32R32F:
                formatName = "RGBA32F";
                blockSize = 16;
                blockWidth = 1;
                blockHeight = 1;
    
              case D3DFMT_R16F:
                formatName = "R16F";
                blockSize = 2;
                blockWidth = 1;
                blockHeight = 1;
    
              case D3DFMT_G16R16F:
                formatName = "RG16F";
                blockSize = 4;
                blockWidth = 1;
                blockHeight = 1;
    
              case D3DFMT_A16B16G16R16F:
                formatName = "RGBA16F";
                blockSize = 8;
                blockWidth = 1;
                blockHeight = 1;
    
              default:
                std::cout << "Unsupported FourCC format.\n";
                return -5;
            }
        }
        else
        {
            std::cout << "Unsupported DDS format.\n";
            return -6;
        }
    
        std::size_t height = header.dwHeight;
        std::size_t width = header.dwWidth;
        std::size_t levels = std::max<size_t>(1, header.dwMipMapCount);
    
        std::ofstream oss(outputFile);
        oss << "// Automatically generated header from " << inputFile << ", a " << width << "x" << height;
        if (levels > 1)
        {
            oss << " (" << levels << " mip levels)";
        }
        oss << "\n// " << formatName << " texture using " << programName << ".\n";
    
        oss << "static const size_t " << outputName << "_width = " << width << ";\n";
        oss << "static const size_t " << outputName << "_height = " << height << ";\n";
        oss << "static const size_t " << outputName << "_levels = " << levels << ";\n";
        oss << "\n";
    
        for (std::size_t i = 0; i < levels; ++i)
        {
            std::size_t widthAtLevel = std::max<size_t>(width >> i, 1);
            std::size_t heightAtLevel = std::max<size_t>(height >> i, 1);
            std::size_t sizeAtLevel = static_cast<std::size_t>(std::ceil(widthAtLevel / static_cast<float>(blockWidth)) *
                                                               std::ceil(heightAtLevel / static_cast<float>(blockHeight))) *
                                      blockSize;
    
            std::vector<unsigned char> data(sizeAtLevel);
            readFile.read(reinterpret_cast<char*>(data.data()), sizeAtLevel);
    
            oss << "static const size_t " << outputName << "_" << i << "_width = " << widthAtLevel << ";\n";
            oss << "static const size_t " << outputName << "_" << i << "_height = " << heightAtLevel << ";\n";
            oss << "static const size_t " << outputName << "_" << i << "_size = " << sizeAtLevel << ";\n";
            oss << "static const unsigned char " << outputName << "_" << i << "_data[" << sizeAtLevel << "] =\n";
            oss << "{";
            for (std::size_t j = 0; j < sizeAtLevel; j++)
            {
                if (j % 16 == 0)
                {
                    oss << "\n    ";
                }
    
                char buffer[32];
                sprintf_s(buffer, "0x%02X,", data[j]);
                oss << std::string(buffer);
            }
            oss << "\n";
            oss << "};\n";
    
            if (i + 1 < levels)
            {
                oss << "\n";
            }
        }
    
        oss.close();
        readFile.close();
    
        return 0;
    }