blob: ab8799c651adfa0671b531332c6d4246134ecfc9 [file] [log] [blame]
//
// Copyright (c) 2002-2010 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.
//
//
// Implement the top-level of interface to the compiler,
// as defined in ShaderLang.h
//
#include "GLSLANG/ShaderLang.h"
#include "compiler/InitializeDll.h"
#include "compiler/ShHandle.h"
//
// This is the platform independent interface between an OGL driver
// and the shading language compiler.
//
static int getVariableMaxLength(const TVariableInfoList& varList)
{
TString::size_type maxLen = 0;
for (TVariableInfoList::const_iterator i = varList.begin();
i != varList.end(); ++i)
{
maxLen = std::max(maxLen, i->name.size());
}
// Add 1 to include null-termination character.
return static_cast<int>(maxLen) + 1;
}
static void getVariableInfo(ShShaderInfo varType,
const ShHandle handle,
int index,
int* length,
int* size,
ShDataType* type,
char* name,
char* mappedName)
{
if (!handle || !size || !type || !name)
return;
ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
(varType == SH_ACTIVE_UNIFORMS));
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return;
const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
compiler->getAttribs() : compiler->getUniforms();
if (index < 0 || index >= static_cast<int>(varList.size()))
return;
const TVariableInfo& varInfo = varList[index];
if (length) *length = varInfo.name.size();
*size = varInfo.size;
*type = varInfo.type;
strcpy(name, varInfo.name.c_str());
if (mappedName)
strcpy(mappedName, varInfo.mappedName.c_str());
}
//
// Driver must call this first, once, before doing any other
// compiler operations.
//
int ShInitialize()
{
if (!InitProcess())
return 0;
return 1;
}
//
// Cleanup symbol tables
//
int ShFinalize()
{
if (!DetachProcess())
return 0;
return 1;
}
//
// Initialize built-in resources with minimum expected values.
//
void ShInitBuiltInResources(ShBuiltInResources* resources)
{
// Constants.
resources->MaxVertexAttribs = 8;
resources->MaxVertexUniformVectors = 128;
resources->MaxVaryingVectors = 8;
resources->MaxVertexTextureImageUnits = 0;
resources->MaxCombinedTextureImageUnits = 8;
resources->MaxTextureImageUnits = 8;
resources->MaxFragmentUniformVectors = 16;
resources->MaxDrawBuffers = 1;
// Extensions.
resources->OES_standard_derivatives = 0;
}
//
// Driver calls these to create and destroy compiler objects.
//
ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
ShShaderOutput output,
const ShBuiltInResources* resources)
{
if (!InitThread())
return 0;
TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return 0;
// Generate built-in symbol table.
if (!compiler->Init(*resources)) {
ShDestruct(base);
return 0;
}
return reinterpret_cast<void*>(base);
}
void ShDestruct(ShHandle handle)
{
if (handle == 0)
return;
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
if (base->getAsCompiler())
DeleteCompiler(base->getAsCompiler());
}
//
// Do an actual compile on the given strings. The result is left
// in the given compile object.
//
// Return: The return value of ShCompile is really boolean, indicating
// success or failure.
//
int ShCompile(
const ShHandle handle,
const char* const shaderStrings[],
const int numStrings,
int compileOptions)
{
if (!InitThread())
return 0;
if (handle == 0)
return 0;
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return 0;
bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
return success ? 1 : 0;
}
void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
{
if (!handle || !params)
return;
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
switch(pname)
{
case SH_INFO_LOG_LENGTH:
*params = compiler->getInfoSink().info.size() + 1;
break;
case SH_OBJECT_CODE_LENGTH:
*params = compiler->getInfoSink().obj.size() + 1;
break;
case SH_ACTIVE_UNIFORMS:
*params = compiler->getUniforms().size();
break;
case SH_ACTIVE_UNIFORM_MAX_LENGTH:
*params = getVariableMaxLength(compiler->getUniforms());
break;
case SH_ACTIVE_ATTRIBUTES:
*params = compiler->getAttribs().size();
break;
case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
*params = getVariableMaxLength(compiler->getAttribs());
break;
case SH_MAPPED_NAME_MAX_LENGTH:
*params = compiler->getMappedNameMaxLength();
break;
default: UNREACHABLE();
}
}
//
// Return any compiler log of messages for the application.
//
void ShGetInfoLog(const ShHandle handle, char* infoLog)
{
if (!handle || !infoLog)
return;
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
TInfoSink& infoSink = compiler->getInfoSink();
strcpy(infoLog, infoSink.info.c_str());
}
//
// Return any object code.
//
void ShGetObjectCode(const ShHandle handle, char* objCode)
{
if (!handle || !objCode)
return;
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
TInfoSink& infoSink = compiler->getInfoSink();
strcpy(objCode, infoSink.obj.c_str());
}
void ShGetActiveAttrib(const ShHandle handle,
int index,
int* length,
int* size,
ShDataType* type,
char* name,
char* mappedName)
{
getVariableInfo(SH_ACTIVE_ATTRIBUTES,
handle, index, length, size, type, name, mappedName);
}
void ShGetActiveUniform(const ShHandle handle,
int index,
int* length,
int* size,
ShDataType* type,
char* name,
char* mappedName)
{
getVariableInfo(SH_ACTIVE_UNIFORMS,
handle, index, length, size, type, name, mappedName);
}