Edit

kc3-lang/angle/src/libGLESv2/D3DConstantTable.cpp

Branch :

  • Show log

    Commit

  • Author : apatrick@chromium.org
    Date : 2012-09-05 22:26:10
    Hash : 60dafe8f
    Message : Implement D3DConstantTable. Remove ProgramBinary dependencies on D3DX. Review URL: https://codereview.appspot.com/6485061 git-svn-id: https://angleproject.googlecode.com/svn/trunk@1271 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/libGLESv2/D3DConstantTable.cpp
  • //
    // Copyright (c) 2012 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.
    //
    
    // D3DConstantTable.cpp: Implements the D3DConstantTable class which parses
    // information about constants from the CTAB comment in a D3D shader blob.
    // Restructures the constant table as a hierarchy of constants in the same
    // way as D3DX.
    
    #include "libGLESv2/D3DConstantTable.h"
    
    #include <d3d9.h>
    #include <d3d9types.h>
    #include <windows.h>
    #include <mmsystem.h>
    
    #include "libGLESv2/BinaryStream.h"
    
    const static int SHADER_VERSION_MASK = D3DVS_VERSION(0, 0);
    const static int FOURCC_CTAB = MAKEFOURCC('C','T','A','B');
    
    namespace gl
    {
    // These structs and constants correspond to the format of the constant table in a shader binary.
    // They match the corresponding structures in d3dx9shader.h.
    namespace ctab
    {
    struct ConstantTable
    {
        DWORD size;
        DWORD creator;
        DWORD version;
        DWORD constants;
        DWORD constantInfos;
        DWORD flags;
        DWORD target;
    };
    
    struct ConstantInfo
    {
        DWORD name;
        WORD registerSet;
        WORD registerIndex;
        WORD registerCount;
        WORD reserved;
        DWORD typeInfo;
        DWORD defaultValue;
    };
    
    struct TypeInfo
    {
        WORD typeClass;
        WORD type;
        WORD rows;
        WORD columns;
        WORD elements;
        WORD structMembers;
        DWORD structMemberInfos;
    };
    
    struct StructMemberInfo
    {
        DWORD name;
        DWORD typeInfo;
    };
    }
    
    D3DConstant::D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo)
    {
        const ctab::TypeInfo *typeInfo = reinterpret_cast<const ctab::TypeInfo*>(base + constantInfo->typeInfo);
    
        name = base + constantInfo->name;
        registerSet = static_cast<RegisterSet>(constantInfo->registerSet);
        registerIndex = constantInfo->registerIndex;
        registerCount = constantInfo->registerCount;
        typeClass = static_cast<Class>(typeInfo->typeClass);
        type = static_cast<Type>(typeInfo->type);
        rows = typeInfo->rows;
        columns = typeInfo->columns;
        elements = typeInfo->elements;
    
        if (typeClass == CLASS_STRUCT)
        {
            addStructMembers(base, registerSet, registerIndex, typeInfo);
        }
    }
    
    D3DConstant::D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::StructMemberInfo *memberInfo)
        : registerSet(registerSet), registerIndex(registerIndex)
    {
        const ctab::TypeInfo *typeInfo = reinterpret_cast<const ctab::TypeInfo*>(base + memberInfo->typeInfo);
    
        name = base + memberInfo->name;
        registerCount = typeInfo->rows * typeInfo->elements;
        typeClass = static_cast<Class>(typeInfo->typeClass);
        type = static_cast<Type>(typeInfo->type);
        rows = typeInfo->rows;
        columns = typeInfo->columns;
        elements = typeInfo->elements;
    
        if (typeClass == CLASS_STRUCT)
        {
            registerCount = addStructMembers(base, registerSet, registerIndex, typeInfo);
        }
    }
    
    D3DConstant::~D3DConstant()
    {
        for (size_t j = 0; j < structMembers.size(); ++j)
        {
            for (size_t i = 0; i < structMembers[j].size(); ++i)
            {
                delete structMembers[j][i];
            }
        }
    }
    
    unsigned D3DConstant::addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::TypeInfo *typeInfo)
    {
        const ctab::StructMemberInfo *memberInfos = reinterpret_cast<const ctab::StructMemberInfo*>(
            base + typeInfo->structMemberInfos);
    
        unsigned memberIndex = registerIndex;
    
        structMembers.resize(elements);
    
        for (unsigned j = 0; j < elements; ++j)
        {
            structMembers[j].resize(typeInfo->structMembers);
    
            for (unsigned i = 0; i < typeInfo->structMembers; ++i)
            {
                const ctab::TypeInfo *memberTypeInfo = reinterpret_cast<const ctab::TypeInfo*>(
                    base + memberInfos[i].typeInfo);
    
                D3DConstant *member = new D3DConstant(base, registerSet, memberIndex, memberInfos + i);
                memberIndex += member->registerCount;
    
                structMembers[j][i] = member;
            }
        }
    
        return memberIndex - registerIndex;
    }
    
    D3DConstantTable::D3DConstantTable(void *blob, size_t size) : mError(false)
    {
        BinaryInputStream stream(blob, size);
    
        int version;
        stream.read(&version);
        if ((version & SHADER_VERSION_MASK) != SHADER_VERSION_MASK)
        {
            mError = true;
            return;
        }
    
        const ctab::ConstantTable* constantTable = NULL;
    
        while (!stream.error())
        {
            int token;
            stream.read(&token);
    
            if ((token & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
            {
                size_t length = ((token & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT) * sizeof(DWORD);
    
                int fourcc;
                stream.read(&fourcc);
                if (fourcc == FOURCC_CTAB)
                {
                    constantTable = reinterpret_cast<const ctab::ConstantTable*>(static_cast<const char*>(blob) + stream.offset());
                    break;
                }
    
                stream.skip(length - sizeof(fourcc));
            }
            else if (token == D3DSIO_END)
            {
                break;
            }
        }
    
        mError = !constantTable || stream.error();
        if (mError)
        {
            return;
        }
    
        const char *base = reinterpret_cast<const char*>(constantTable);
    
        mConstants.resize(constantTable->constants);
        const ctab::ConstantInfo *constantInfos =
            reinterpret_cast<const ctab::ConstantInfo*>(base + constantTable->constantInfos);
        for (size_t i = 0; i < constantTable->constants; ++i)
        {
            mConstants[i] = new D3DConstant(base, constantInfos + i);
        }
    }
    
    D3DConstantTable::~D3DConstantTable()
    {
        for (size_t i = 0; i < mConstants.size(); ++i)
        {
            delete mConstants[i];
        }
    }
    
    const D3DConstant *D3DConstantTable::getConstant(unsigned index) const
    {
        return mConstants[index];
    }
    
    const D3DConstant *D3DConstantTable::getConstantByName(const char *name) const
    {
        for (size_t i = 0; i < mConstants.size(); ++i)
        {
            const D3DConstant *constant = getConstant(i);
            if (constant->name == name)
            {
                return constant;
            }
        }
    
        return NULL;
    }
    
    }