diff options
Diffstat (limited to 'o3d/gpu/command_buffer/service/effect_gl.cc')
-rw-r--r-- | o3d/gpu/command_buffer/service/effect_gl.cc | 852 |
1 files changed, 0 insertions, 852 deletions
diff --git a/o3d/gpu/command_buffer/service/effect_gl.cc b/o3d/gpu/command_buffer/service/effect_gl.cc deleted file mode 100644 index b8f9601..0000000 --- a/o3d/gpu/command_buffer/service/effect_gl.cc +++ /dev/null @@ -1,852 +0,0 @@ -/* - * Copyright 2009, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -// This file contains the implementation of the EffectParamGL and EffectGL -// classes, as well as the effect-related GAPI functions on GL. - -#include "gpu/command_buffer/service/precompile.h" - -#include <map> - -#include "base/cross/std_functional.h" -#include "gpu/command_buffer/service/effect_gl.h" -#include "gpu/command_buffer/service/gapi_gl.h" -#include "gpu/command_buffer/service/effect_utils.h" - -namespace command_buffer { -namespace o3d { - -EffectParamGL::EffectParamGL(effect_param::DataType data_type, - EffectGL *effect, - unsigned int param_index) - : EffectParam(data_type), - effect_(effect), - low_level_param_index_(param_index) { - DCHECK(effect_); - effect_->LinkParam(this); -} - -EffectParamGL::~EffectParamGL() { - if (effect_) - effect_->UnlinkParam(this); -} - -static effect_param::DataType CgTypeToCBType(CGtype cg_type) { - switch (cg_type) { - case CG_FLOAT: - case CG_FLOAT1: - return effect_param::kFloat1; - case CG_FLOAT2: - return effect_param::kFloat2; - case CG_FLOAT3: - return effect_param::kFloat3; - case CG_FLOAT4: - return effect_param::kFloat4; - case CG_INT: - case CG_INT1: - return effect_param::kInt; - case CG_BOOL: - case CG_BOOL1: - return effect_param::kBool; - case CG_FLOAT4x4: - return effect_param::kMatrix4; - case CG_SAMPLER: - case CG_SAMPLER1D: - case CG_SAMPLER2D: - case CG_SAMPLER3D: - case CG_SAMPLERCUBE: - return effect_param::kSampler; - case CG_TEXTURE: - return effect_param::kTexture; - default : { - DLOG(INFO) << "Cannot convert CGtype " - << cgGetTypeString(cg_type) - << " to a Param type."; - return effect_param::kUnknown; - } - } -} - -EffectParamGL *EffectParamGL::Create(EffectGL *effect, - unsigned int index) { - DCHECK(effect); - const EffectGL::LowLevelParam &low_level_param = - effect->low_level_params_[index]; - CGparameter cg_param = EffectGL::GetEitherCgParameter(low_level_param); - CGtype cg_type = cgGetParameterType(cg_param); - if (cg_type == CG_ARRAY) { - cg_type = cgGetParameterType(cgGetArrayParameter(cg_param, 0)); - } - effect_param::DataType type = CgTypeToCBType(cg_type); - - if (type == effect_param::kUnknown) - return NULL; - return new EffectParamGL(type, effect, index); -} - -// Fills the Desc structure, appending name and semantic if any, and if enough -// room is available in the buffer. -bool EffectParamGL::GetDesc(unsigned int size, void *data) { - using effect_param::Desc; - if (size < sizeof(Desc)) // NOLINT - return false; - if (!effect_) - return false; - const EffectGL::LowLevelParam &low_level_param = - effect_->low_level_params_[low_level_param_index_]; - CGparameter cg_param = EffectGL::GetEitherCgParameter(low_level_param); - const char *name = low_level_param.name; - const char* semantic = cgGetParameterSemantic(cg_param); - int num_elements = cgGetArraySize(cg_param, 0); - unsigned int name_size = - name ? static_cast<unsigned int>(strlen(name)) + 1 : 0; - unsigned int semantic_size = semantic ? - static_cast<unsigned int>(strlen(semantic)) + 1 : 0; - unsigned int total_size = sizeof(Desc) + name_size + semantic_size; // NOLINT - - Desc *desc = static_cast<Desc *>(data); - memset(desc, 0, sizeof(*desc)); - desc->size = total_size; - desc->data_type = data_type(); - desc->data_size = GetDataSize(data_type()); - desc->name_offset = 0; - desc->name_size = name_size; - desc->semantic_offset = 0; - desc->num_elements = num_elements; - desc->semantic_size = semantic_size; - unsigned int current_offset = sizeof(Desc); - if (name && current_offset + name_size <= size) { - desc->name_offset = current_offset; - memcpy(static_cast<char *>(data) + current_offset, name, name_size); - current_offset += name_size; - } - if (semantic && current_offset + semantic_size <= size) { - desc->semantic_offset = current_offset; - memcpy(static_cast<char *>(data) + current_offset, semantic, semantic_size); - current_offset += semantic_size; - } - return true; -} - -// Sets the data into the Cg effect parameter, using the appropriate Cg call. -bool EffectParamGL::SetData(GAPIGL *gapi, - unsigned int size, - const void * data) { - if (!effect_) - return false; - - EffectGL::LowLevelParam &low_level_param = - effect_->low_level_params_[low_level_param_index_]; - - if (low_level_param.num_elements != 0) { - DLOG(ERROR) << "Attempt to set array parameter to value."; - return false; - } - - CGparameter vp_param = low_level_param.vp_param; - CGparameter fp_param = low_level_param.fp_param; - effect_param::DataType type = data_type(); - if (size < effect_param::GetDataSize(type)) - return false; - - switch (type) { - case effect_param::kFloat1: - if (vp_param) - cgSetParameter1f(vp_param, *static_cast<const float *>(data)); - if (fp_param) - cgSetParameter1f(fp_param, *static_cast<const float *>(data)); - break; - case effect_param::kFloat2: - if (vp_param) - cgSetParameter2fv(vp_param, static_cast<const float *>(data)); - if (fp_param) - cgSetParameter2fv(fp_param, static_cast<const float *>(data)); - break; - case effect_param::kFloat3: - if (vp_param) - cgSetParameter3fv(vp_param, static_cast<const float *>(data)); - if (fp_param) - cgSetParameter3fv(fp_param, static_cast<const float *>(data)); - break; - case effect_param::kFloat4: - if (vp_param) - cgSetParameter4fv(vp_param, static_cast<const float *>(data)); - if (fp_param) - cgSetParameter4fv(fp_param, static_cast<const float *>(data)); - break; - case effect_param::kMatrix4: - if (vp_param) - cgSetMatrixParameterfr(vp_param, static_cast<const float *>(data)); - if (fp_param) - cgSetMatrixParameterfr(fp_param, static_cast<const float *>(data)); - break; - case effect_param::kInt: - if (vp_param) cgSetParameter1i(vp_param, *static_cast<const int *>(data)); - if (fp_param) cgSetParameter1i(fp_param, *static_cast<const int *>(data)); - break; - case effect_param::kBool: { - int bool_value = *static_cast<const bool *>(data)?1:0; - if (vp_param) cgSetParameter1i(vp_param, bool_value); - if (fp_param) cgSetParameter1i(fp_param, bool_value); - break; - } - case effect_param::kSampler: { - DCHECK_GE(low_level_param.sampler_ids.size(), 1U); - low_level_param.sampler_ids[0] = *static_cast<const ResourceId *>(data); - if (effect_ == gapi->current_effect()) { - gapi->DirtyEffect(); - } - break; - } - default: - DLOG(ERROR) << "Invalid parameter type."; - return false; - } - return true; -} -EffectGL::EffectGL(CGprogram vertex_program, - CGprogram fragment_program) - : vertex_program_(vertex_program), - fragment_program_(fragment_program), - update_samplers_(true) { -} - -EffectGL::~EffectGL() { - for (ParamList::iterator it = params_.begin(); - it != params_.end(); ++it) { - (*it)->ResetEffect(); - } -} - -void EffectGL::LinkParam(EffectParamGL *param) { - params_.push_back(param); -} - -void EffectGL::UnlinkParam(EffectParamGL *param) { - std::remove(params_.begin(), params_.end(), param); -} - -// Rewrites vertex program assembly code to match GL semantics for clipping. -// This parses the source, breaking it down into pieces: -// - declaration ("!!ARBvp1.0") -// - comments (that contain the parameter information) -// - instructions -// - "END" token. -// Then it rewrites the instructions so that 'result.position' doesn't get -// written directly, instead it is written to a temporary variable. Then a -// transformation is done on that variable before outputing to -// 'result.position': -// - offset x an y by half a pixel (times w). -// - remap z from [0..w] to [-w..w]. -// -// Note that for the 1/2 pixel offset, we need a parameter that depends on the -// current viewport. This is done through 'program.env[0]' which is shared -// across all programs (so we only have to update it once when we change the -// viewport), because Cg won't use them currently (it uses 'program.local' -// instead). -static bool RewriteVertexProgramSource(String *source) { - String::size_type pos = source->find('\n'); - if (pos == String::npos) { - DLOG(ERROR) << "could not find program declaration"; - return false; - } - String decl(*source, 0, pos + 1); - String::size_type start_comments = pos + 1; - // skip the comments that contain the parameters etc. - for (; pos < source->size(); pos = source->find('\n', pos)) { - ++pos; - if (pos >= source->size()) - break; - if ((*source)[pos] != '#') - break; - } - if (pos >= source->size()) { - // we only found comments. - return false; - } - String comments(*source, start_comments, pos - start_comments); - - String::size_type end_token = source->find("\nEND", pos + 1); - if (end_token == String::npos) { - DLOG(ERROR) << "Compiled shader doesn't have an END token"; - return false; - } - String instructions(*source, pos, end_token + 1 - pos); - - // Replace accesses to 'result.position' by accesses to our temp variable - // '$O3D_HPOS'. - // '$' is a valid symbol for identifiers, but Cg doesn't seem to be using - // it, so we can use it to ensure we don't have name conflicts. - static const char kOutPositionRegister[] = "result.position"; - for (String::size_type i = instructions.find(kOutPositionRegister); - i < String::npos; i = instructions.find(kOutPositionRegister, i)) { - instructions.replace(i, strlen(kOutPositionRegister), "$O3D_HPOS"); - } - - *source = decl + - comments + - // .x = 1/viewport.width; .y = 1/viewport.height; .z = 2.0; - "PARAM $O3D_HELPER = program.env[0];\n" - "TEMP $O3D_HPOS;\n" + - instructions + - // hpos.x <- hpos.x + hpos.w / viewport.width; - // hpos.y <- hpos.y - hpos.w / viewport.height; - "MAD $O3D_HPOS.xy, $O3D_HELPER.xyyy, $O3D_HPOS.w, $O3D_HPOS.xyyy;\n" - // hpos.z <- hpos.z * 2 - hpos.w - "MAD $O3D_HPOS.z, $O3D_HPOS.z, $O3D_HELPER.z, -$O3D_HPOS.w;\n" - "MOV result.position, $O3D_HPOS;\n" - "END\n"; - return true; -} - -EffectGL *EffectGL::Create(GAPIGL *gapi, - const String& effect_code, - const String& vertex_program_entry, - const String& fragment_program_entry) { - CGcontext context = gapi->cg_context(); - // Compile the original vertex program once, to get the ARBVP1 assembly code. - CGprogram original_vp = cgCreateProgram( - context, CG_SOURCE, effect_code.c_str(), CG_PROFILE_ARBVP1, - vertex_program_entry.c_str(), NULL); - const char* listing = cgGetLastListing(context); - if (original_vp == NULL) { - DLOG(ERROR) << "Effect Compile Error: " << cgGetErrorString(cgGetError()) - << " : " << listing; - return NULL; - } - - if (listing && listing[0] != 0) { - DLOG(WARNING) << "Effect Compile Warnings: " << listing; - } - - String vp_assembly = cgGetProgramString(original_vp, CG_COMPILED_PROGRAM); - cgDestroyProgram(original_vp); - if (!RewriteVertexProgramSource(&vp_assembly)) { - return NULL; - } - CGprogram vertex_program = cgCreateProgram( - context, CG_OBJECT, vp_assembly.c_str(), CG_PROFILE_ARBVP1, - vertex_program_entry.c_str(), NULL); - listing = cgGetLastListing(context); - if (vertex_program == NULL) { - DLOG(ERROR) << "Effect post-rewrite Compile Error: " - << cgGetErrorString(cgGetError()) << " : " << listing; - return false; - } - - if (listing && listing[0] != 0) { - DLOG(WARNING) << "Effect post-rewrite compile warnings: " << listing; - } - - CHECK_GL_ERROR(); - - // If the program rewrite introduced some syntax or semantic errors, we won't - // know it until we load the program (through a GL error). - // So flush all GL errors first... - do {} while (glGetError() != GL_NO_ERROR); - - // ... Then load the program ... - cgGLLoadProgram(vertex_program); - - // ... And check for GL errors. - if (glGetError() != GL_NO_ERROR) { - DLOG(ERROR) << "Effect post-rewrite GL Error: " - << glGetString(GL_PROGRAM_ERROR_STRING_ARB) - << "\nSource: \n" - << vp_assembly; - return NULL; - } - - CGprogram fragment_program = cgCreateProgram( - context, CG_SOURCE, effect_code.c_str(), CG_PROFILE_ARBFP1, - fragment_program_entry.c_str(), NULL); - listing = cgGetLastListing(context); - if (fragment_program == NULL) { - DLOG(ERROR) << "Effect Compile Error: " - << cgGetErrorString(cgGetError()) << " : " - << listing; - return NULL; - } - - if (listing && listing[0] != 0) { - DLOG(WARNING) << "Effect Compile Warnings: " << listing; - } - - cgGLLoadProgram(fragment_program); - - // Also check for GL errors, in case Cg managed to compile, but generated a - // bad program. - if (glGetError() != GL_NO_ERROR) { - DLOG(ERROR) << "Effect GL Error: " - << glGetString(GL_PROGRAM_ERROR_STRING_ARB); - return false; - } - EffectGL *effect = new EffectGL(vertex_program, fragment_program); - effect->Initialize(); - return effect; -} - -int EffectGL::GetLowLevelParamIndexByName(const char *name) { - DCHECK(name); - for (unsigned int index = 0; index < low_level_params_.size(); ++index) { - if (!strcmp(name, low_level_params_[index].name)) { - return index; - } - } - return -1; -} - -void EffectGL::AddLowLevelParams(CGprogram prog, CGenum name_space, bool vp) { - // Iterate through parameters and add them to the vector of low level - // parameters, visiting only CGparameters that have had storage allocated to - // them, and add the params to the low_level_params_ vector. - for (CGparameter cg_param = cgGetFirstParameter(prog, name_space); - cg_param != NULL; - cg_param = cgGetNextParameter(cg_param)) { - CGenum variability = cgGetParameterVariability(cg_param); - if (variability != CG_UNIFORM) - continue; - CGenum direction = cgGetParameterDirection(cg_param); - if (direction != CG_IN) - continue; - const char *name = cgGetParameterName(cg_param); - if (!name) - continue; - - CGtype cg_type = cgGetParameterType(cg_param); - - int num_elements; - if (cg_type == CG_ARRAY) { - num_elements = cgGetArraySize(cg_param, 0); - // Substitute the first element's type for our type. - cg_type = cgGetParameterType(cgGetArrayParameter(cg_param, 0)); - } else { - num_elements = 0; - } - - int index = GetLowLevelParamIndexByName(name); - if (index < 0) { - LowLevelParam param; - param.name = name; - param.vp_param = NULL; - param.fp_param = NULL; - param.num_elements = num_elements; - - index = low_level_params_.size(); - if (cg_type == CG_SAMPLER || - cg_type == CG_SAMPLER1D || - cg_type == CG_SAMPLER2D || - cg_type == CG_SAMPLER3D || - cg_type == CG_SAMPLERCUBE) { - sampler_params_.push_back(index); - if (num_elements == 0) { - param.sampler_ids.push_back(kInvalidResource); - } else { - param.sampler_ids.resize(num_elements); - std::vector<ResourceId>::iterator iter; - for (iter = param.sampler_ids.begin(); - iter != param.sampler_ids.end(); - ++iter) { - *iter = kInvalidResource; - } - } - } - low_level_params_.push_back(param); - } - - if (vp) { - low_level_params_[index].vp_param = cg_param; - } else { - low_level_params_[index].fp_param = cg_param; - } - } -} - -typedef std::pair<String, effect_stream::Desc> SemanticMapElement; -typedef std::map<String, effect_stream::Desc> SemanticMap; - -// The map batween the semantics on vertex program varying parameters names -// and vertex attribute indices under the VP_30 profile. -// TODO(gman): remove this. -SemanticMapElement semantic_map_array[] = { - SemanticMapElement("POSITION", - effect_stream::Desc(vertex_struct::kPosition, 0)), - SemanticMapElement("ATTR0", - effect_stream::Desc(vertex_struct::kPosition, 0)), - SemanticMapElement("BLENDWEIGHT", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("ATTR1", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("NORMAL", - effect_stream::Desc(vertex_struct::kNormal, 0)), - SemanticMapElement("ATTR2", - effect_stream::Desc(vertex_struct::kNormal, 0)), - SemanticMapElement("COLOR0", - effect_stream::Desc(vertex_struct::kColor, 0)), - SemanticMapElement("DIFFUSE", - effect_stream::Desc(vertex_struct::kColor, 0)), - SemanticMapElement("ATTR3", - effect_stream::Desc(vertex_struct::kColor, 0)), - SemanticMapElement("COLOR1", - effect_stream::Desc(vertex_struct::kColor, 1)), - SemanticMapElement("SPECULAR", - effect_stream::Desc(vertex_struct::kColor, 1)), - SemanticMapElement("ATTR4", - effect_stream::Desc(vertex_struct::kColor, 1)), - SemanticMapElement("TESSFACTOR", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("FOGCOORD", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("ATTR5", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("PSIZE", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("ATTR6", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("BLENDINDICES", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("ATTR7", - effect_stream::Desc(vertex_struct::kUnknownSemantic, 0)), - SemanticMapElement("TEXCOORD0", - effect_stream::Desc(vertex_struct::kTexCoord, 0)), - SemanticMapElement("ATTR8", - effect_stream::Desc(vertex_struct::kTexCoord, 0)), - SemanticMapElement("TEXCOORD1", - effect_stream::Desc(vertex_struct::kTexCoord, 1)), - SemanticMapElement("ATTR9", - effect_stream::Desc(vertex_struct::kTexCoord, 1)), - SemanticMapElement("TEXCOORD2", - effect_stream::Desc(vertex_struct::kTexCoord, 2)), - SemanticMapElement("ATTR10", - effect_stream::Desc(vertex_struct::kTexCoord, 2)), - SemanticMapElement("TEXCOORD3", - effect_stream::Desc(vertex_struct::kTexCoord, 3)), - SemanticMapElement("ATTR11", - effect_stream::Desc(vertex_struct::kTexCoord, 3)), - SemanticMapElement("TEXCOORD4", - effect_stream::Desc(vertex_struct::kTexCoord, 4)), - SemanticMapElement("ATTR12", - effect_stream::Desc(vertex_struct::kTexCoord, 4)), - SemanticMapElement("TEXCOORD5", - effect_stream::Desc(vertex_struct::kTexCoord, 5)), - SemanticMapElement("ATTR13", - effect_stream::Desc(vertex_struct::kTexCoord, 5)), - SemanticMapElement("TEXCOORD6", - effect_stream::Desc(vertex_struct::kTexCoord, 6)), - SemanticMapElement("TANGENT", - effect_stream::Desc(vertex_struct::kTexCoord, 6)), - SemanticMapElement("ATTR14", - effect_stream::Desc(vertex_struct::kTexCoord, 7)), - SemanticMapElement("TEXCOORD7", - effect_stream::Desc(vertex_struct::kTexCoord, 7)), - SemanticMapElement("BINORMAL", - effect_stream::Desc(vertex_struct::kTexCoord, 8)), - SemanticMapElement("ATTR15", - effect_stream::Desc(vertex_struct::kTexCoord, 8)) -}; - -static SemanticMap semantic_map(semantic_map_array, - semantic_map_array + - arraysize(semantic_map_array)); - -void EffectGL::Initialize() { - AddLowLevelParams(vertex_program_, CG_PROGRAM, true); - AddLowLevelParams(vertex_program_, CG_GLOBAL, true); - AddLowLevelParams(fragment_program_, CG_PROGRAM, false); - AddLowLevelParams(fragment_program_, CG_GLOBAL, false); - - AddStreams(vertex_program_, CG_PROGRAM); - AddStreams(vertex_program_, CG_GLOBAL); -} - -// Loop over all leaf parameters, and find the ones that are bound to a -// semantic. -void EffectGL::AddStreams(CGprogram prog, CGenum name_space) { - for (CGparameter cg_param = cgGetFirstLeafParameter(prog, name_space); - cg_param != NULL; - cg_param = cgGetNextLeafParameter(cg_param)) { - CGenum variability = cgGetParameterVariability(cg_param); - if (variability != CG_VARYING) - continue; - CGenum direction = cgGetParameterDirection(cg_param); - if (direction != CG_IN) - continue; - const char* cg_semantic = cgGetParameterSemantic(cg_param); - if (cg_semantic == NULL) - continue; - - SemanticMap::iterator iter = semantic_map.find(String(cg_semantic)); - if (iter == semantic_map.end()) { - streams_.push_back(effect_stream::Desc( - vertex_struct::kUnknownSemantic, 0)); - } else { - streams_.push_back(iter->second); - } - } -} - -// Begins rendering with the effect, setting all the appropriate states. -bool EffectGL::Begin(GAPIGL *gapi) { - cgGLBindProgram(vertex_program_); - cgGLBindProgram(fragment_program_); - - // sampler->ApplyStates will mess with the texture binding on unit 0, so we - // do 2 passes. - // First to set the sampler states on the texture - for (unsigned int i = 0; i < sampler_params_.size(); ++i) { - unsigned int param_index = sampler_params_[i]; - std::vector<ResourceId> &ids = low_level_params_[param_index].sampler_ids; - for (std::vector<ResourceId>::iterator iter = ids.begin(); - iter != ids.end(); - ++iter) { - ResourceId id = *iter; - if (id != kInvalidResource) { - SamplerGL *sampler = gapi->GetSampler(id); - if (!sampler->ApplyStates(gapi)) { - return false; - } - } - } - } - // Second to enable/disable the sampler params. - for (unsigned int i = 0; i < sampler_params_.size(); ++i) { - unsigned int param_index = sampler_params_[i]; - const LowLevelParam &ll_param = low_level_params_[param_index]; - std::vector<ResourceId> &ids = low_level_params_[param_index].sampler_ids; - // TODO(petersont): Rewrite the following so it handles arrays of samplers - // instead of simply bailing. - if (cgGetParameterType(ll_param.fp_param) == CG_ARRAY) - return false; - for (std::vector<ResourceId>::iterator iter = ids.begin(); - iter != ids.end(); - ++iter) { - ResourceId id = *iter; - if (id != kInvalidResource) { - SamplerGL *sampler = gapi->GetSampler(id); - GLuint gl_texture = sampler->gl_texture(); - cgGLSetTextureParameter(ll_param.fp_param, gl_texture); - cgGLEnableTextureParameter(ll_param.fp_param); - } else { - cgGLSetTextureParameter(ll_param.fp_param, 0); - cgGLDisableTextureParameter(ll_param.fp_param); - } - } - } - return true; -} - -// Terminates rendering with the effect, resetting all the appropriate states. -void EffectGL::End(GAPIGL *gapi) { -} - -// Gets the parameter count from the list. -unsigned int EffectGL::GetParamCount() const { - return low_level_params_.size(); -} - -// Gets the number of input streams from the shader. -unsigned int EffectGL::GetStreamCount() const { - return streams_.size(); -} - -// Gets a handle to the selected parameter, and wraps it into an -// EffectParamGL if successful. -EffectParamGL *EffectGL::CreateParam(unsigned int index) { - if (index >= GetParamCount()) - return NULL; - return EffectParamGL::Create(this, index); -} - -// Provided enough room is available in the buffer, fills the Desc structure, -// appending name and semantic if any. -bool EffectGL::GetStreamDesc(unsigned int index, - unsigned int size, - void *data) { - using effect_stream::Desc; - if (size < sizeof(Desc) || index >= streams_.size()) // NOLINT - return false; - - Desc *desc = static_cast<Desc *>(data); - *desc = streams_[index]; - return true; -} - -// Gets a handle to the selected parameter, and wraps it into an -// EffectParamGL if successful. -EffectParamGL *EffectGL::CreateParamByName(const char *name) { - int index = GetLowLevelParamIndexByName(name); - if (index < 0) return NULL; - return EffectParamGL::Create(this, index); -} - -parse_error::ParseError GAPIGL::CreateEffect(ResourceId id, - unsigned int size, - const void *data) { - if (id == current_effect_id_) DirtyEffect(); - // Even though Assign would Destroy the effect at id, we do it explicitly in - // case the creation fails. - effects_.Destroy(id); - // Data is vp_main \0 fp_main \0 effect_text. - String vertex_program_entry; - String fragment_program_entry; - String effect_code; - if (!ParseEffectData(size, data, - &vertex_program_entry, - &fragment_program_entry, - &effect_code)) { - return parse_error::kParseInvalidArguments; - } - EffectGL * effect = EffectGL::Create(this, effect_code, - vertex_program_entry, - fragment_program_entry); - if (!effect) return parse_error::kParseInvalidArguments; - effects_.Assign(id, effect); - return parse_error::kParseNoError; -} - -parse_error::ParseError GAPIGL::DestroyEffect(ResourceId id) { - if (id == current_effect_id_) DirtyEffect(); - return effects_.Destroy(id) ? - parse_error::kParseNoError : - parse_error::kParseInvalidArguments; -} - -parse_error::ParseError GAPIGL::SetEffect(ResourceId id) { - DirtyEffect(); - current_effect_id_ = id; - return parse_error::kParseNoError; -} - -parse_error::ParseError GAPIGL::GetParamCount(ResourceId id, - unsigned int size, - void *data) { - EffectGL *effect = effects_.Get(id); - if (!effect || size < sizeof(Uint32)) // NOLINT - return parse_error::kParseInvalidArguments; - *static_cast<Uint32 *>(data) = effect->GetParamCount(); - return parse_error::kParseNoError; -} - -parse_error::ParseError GAPIGL::CreateParam(ResourceId param_id, - ResourceId effect_id, - unsigned int index) { - EffectGL *effect = effects_.Get(effect_id); - if (!effect) return parse_error::kParseInvalidArguments; - EffectParamGL *param = effect->CreateParam(index); - if (!param) return parse_error::kParseInvalidArguments; - effect_params_.Assign(param_id, param); - return parse_error::kParseNoError; -} - -parse_error::ParseError GAPIGL::CreateParamByName(ResourceId param_id, - ResourceId effect_id, - unsigned int size, - const void *name) { - EffectGL *effect = effects_.Get(effect_id); - if (!effect) return parse_error::kParseInvalidArguments; - std::string string_name(static_cast<const char *>(name), size); - EffectParamGL *param = effect->CreateParamByName(string_name.c_str()); - if (!param) return parse_error::kParseInvalidArguments; - effect_params_.Assign(param_id, param); - return parse_error::kParseNoError; -} - -parse_error::ParseError GAPIGL::DestroyParam(ResourceId id) { - return effect_params_.Destroy(id) ? - parse_error::kParseNoError : - parse_error::kParseInvalidArguments; -} - -parse_error::ParseError GAPIGL::SetParamData(ResourceId id, - unsigned int size, - const void *data) { - EffectParamGL *param = effect_params_.Get(id); - if (!param) return parse_error::kParseInvalidArguments; - return param->SetData(this, size, data) ? - parse_error::kParseNoError : - parse_error::kParseInvalidArguments; -} - -parse_error::ParseError GAPIGL::GetParamDesc(ResourceId id, - unsigned int size, - void *data) { - EffectParamGL *param = effect_params_.Get(id); - if (!param) return parse_error::kParseInvalidArguments; - return param->GetDesc(size, data) ? - parse_error::kParseNoError : - parse_error::kParseInvalidArguments; -} - -parse_error::ParseError GAPIGL::GetStreamCount( - ResourceId id, - unsigned int size, - void *data) { - EffectGL *effect = effects_.Get(id); - if (!effect || size < sizeof(Uint32)) // NOLINT - return parse_error::kParseInvalidArguments; - *static_cast<Uint32 *>(data) = effect->GetStreamCount(); - return parse_error::kParseNoError; -} - -parse_error::ParseError GAPIGL::GetStreamDesc(ResourceId id, - unsigned int index, - unsigned int size, - void *data) { - EffectGL *effect = effects_.Get(id); - if (!effect) return parse_error::kParseInvalidArguments; - return effect->GetStreamDesc(index, size, data) ? - parse_error::kParseNoError : - parse_error::kParseInvalidArguments; -} - -// If the current effect is valid, call End on it, and tag for revalidation. -void GAPIGL::DirtyEffect() { - if (validate_effect_) return; - DCHECK(current_effect_); - current_effect_->End(this); - current_effect_ = NULL; - validate_effect_ = true; -} - -// Gets the current effect, and calls Begin on it (if successful). -// Should only be called if the current effect is not valid. -bool GAPIGL::ValidateEffect() { - DCHECK(validate_effect_); - DCHECK(!current_effect_); - current_effect_ = effects_.Get(current_effect_id_); - if (!current_effect_) return false; - validate_effect_ = false; - return current_effect_->Begin(this); -} - -} // namespace o3d -} // namespace command_buffer |