// // 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 #include #include #include #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(base + constantInfo->typeInfo); name = base + constantInfo->name; registerSet = static_cast(constantInfo->registerSet); registerIndex = constantInfo->registerIndex; registerCount = constantInfo->registerCount; typeClass = static_cast(typeInfo->typeClass); type = static_cast(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(base + memberInfo->typeInfo); name = base + memberInfo->name; registerCount = typeInfo->rows * typeInfo->elements; typeClass = static_cast(typeInfo->typeClass); type = static_cast(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( 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( 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(static_cast(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(constantTable); mConstants.resize(constantTable->constants); const ctab::ConstantInfo *constantInfos = reinterpret_cast(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; } }