diff options
Diffstat (limited to 'o3d/command_buffer/client/cross/effect_helper.cc')
-rw-r--r-- | o3d/command_buffer/client/cross/effect_helper.cc | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/o3d/command_buffer/client/cross/effect_helper.cc b/o3d/command_buffer/client/cross/effect_helper.cc new file mode 100644 index 0000000..0cab6ee --- /dev/null +++ b/o3d/command_buffer/client/cross/effect_helper.cc @@ -0,0 +1,211 @@ +/* + * 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 implements the EffectHelper class. + +#include "command_buffer/common/cross/cmd_buffer_format.h" +#include "command_buffer/client/cross/cmd_buffer_helper.h" +#include "command_buffer/client/cross/effect_helper.h" +#include "command_buffer/client/cross/fenced_allocator.h" +#include "command_buffer/client/cross/id_allocator.h" + +// TODO: write a unit test. + +namespace o3d { +namespace command_buffer { + +bool EffectHelper::CreateEffectParameters(ResourceID effect_id, + std::vector<EffectParamDesc> *descs) { + using effect_param::Desc; + DCHECK_NE(effect_id, kInvalidResource); + DCHECK(descs); + descs->clear(); + + // Get the param count. + Uint32 *retval = shm_allocator_->AllocTyped<Uint32>(1); + CommandBufferEntry args[4]; + args[0].value_uint32 = effect_id; + args[1].value_uint32 = sizeof(*retval); + args[2].value_uint32 = shm_id_; + args[3].value_uint32 = shm_allocator_->GetOffset(retval); + helper_->AddCommand(GET_PARAM_COUNT, 4, args); + // Finish has to be called to get the result. + helper_->Finish(); + + // We could have failed if the effect_id is invalid. + if (helper_->interface()->GetParseError() != + BufferSyncInterface::PARSE_NO_ERROR) { + shm_allocator_->Free(retval); + return false; + } + unsigned int param_count = *retval; + + shm_allocator_->Free(retval); + unsigned int max_buffer_size = shm_allocator_->GetLargestFreeOrPendingSize(); + if (max_buffer_size < sizeof(Desc)) { // NOLINT + // Not enough memory to get at least 1 param desc. + return false; + } + descs->resize(param_count); + for (unsigned int i = 0; i < param_count; ++i) { + EffectParamDesc *desc = &((*descs)[i]); + desc->id = param_id_allocator_->AllocateID(); + args[0].value_uint32 = desc->id; + args[1].value_uint32 = effect_id; + args[2].value_uint32 = i; + helper_->AddCommand(CREATE_PARAM, 3, args); + } + + // Read param descriptions in batches. We use as much shared memory as + // possible so that we only call Finish as little as possible. + unsigned int max_param_per_batch = + std::min(param_count, max_buffer_size / sizeof(Desc)); // NOLINT + Desc *raw_descs = shm_allocator_->AllocTyped<Desc>(max_param_per_batch); + DCHECK(raw_descs); + for (unsigned int i = 0; i < param_count; i += max_param_per_batch) { + unsigned int count = std::min(param_count - i, max_param_per_batch); + for (unsigned int j = 0 ; j < count; ++j) { + EffectParamDesc *desc = &((*descs)[i + j]); + Desc *raw_desc = raw_descs + j; + args[0].value_uint32 = desc->id; + args[1].value_uint32 = sizeof(*raw_desc); + args[2].value_uint32 = shm_id_; + args[3].value_uint32 = shm_allocator_->GetOffset(raw_desc); + helper_->AddCommand(GET_PARAM_DESC, 4, args); + } + // Finish to get the results. + helper_->Finish(); + DCHECK_EQ(helper_->interface()->GetParseError(), + BufferSyncInterface::PARSE_NO_ERROR); + for (unsigned int j = 0 ; j < count; ++j) { + EffectParamDesc *desc = &((*descs)[i + j]); + Desc *raw_desc = raw_descs + j; + desc->data_type = raw_desc->data_type; + desc->data_size = raw_desc->data_size; + desc->cmd_desc_size = raw_desc->size; + } + } + shm_allocator_->Free(raw_descs); + return true; +} + +bool EffectHelper::GetParamStrings(EffectParamDesc *desc) { + using effect_param::Desc; + DCHECK(desc); + DCHECK_NE(desc->id, kInvalidResource); + // desc may not have come directly from CreateEffectParameters, so it may be + // less than the minimum required size. + unsigned int size = std::max(desc->cmd_desc_size, sizeof(Desc)); // NOLINT + Desc *raw_desc = static_cast<Desc *>(shm_allocator_->Alloc(size)); + if (!raw_desc) { + // Not enough memory to get the param desc. + return false; + } + CommandBufferEntry args[4]; + args[0].value_uint32 = desc->id; + args[1].value_uint32 = size; + args[2].value_uint32 = shm_id_; + args[3].value_uint32 = shm_allocator_->GetOffset(raw_desc); + helper_->AddCommand(GET_PARAM_DESC, 4, args); + // Finish to get the results. + helper_->Finish(); + + // We could have failed if the param ID is invalid. + if (helper_->interface()->GetParseError() != + BufferSyncInterface::PARSE_NO_ERROR) { + shm_allocator_->Free(raw_desc); + return false; + } + + if (raw_desc->size > size) { + // We had not allocated enough memory the first time (e.g. if the + // EffectParamDesc didn't come from CreateEffectParameters, so the user had + // no way of knowing what size was needed for the strings), so re-allocate + // and try again. + size = raw_desc->size; + desc->cmd_desc_size = size; + shm_allocator_->Free(raw_desc); + raw_desc = static_cast<Desc *>(shm_allocator_->Alloc(size)); + if (!raw_desc) { + // Not enough memory to get the param desc. + return false; + } + args[1].value_uint32 = size; + args[3].value_uint32 = shm_allocator_->GetOffset(raw_desc); + helper_->AddCommand(GET_PARAM_DESC, 4, args); + // Finish to get the results. + helper_->Finish(); + DCHECK_EQ(helper_->interface()->GetParseError(), + BufferSyncInterface::PARSE_NO_ERROR); + DCHECK_EQ(raw_desc->size, size); + } + + const char *raw_desc_string = reinterpret_cast<char *>(raw_desc); + if (raw_desc->name_offset) { + DCHECK_LE(raw_desc->name_offset + raw_desc->name_size, raw_desc->size); + DCHECK_GT(raw_desc->name_size, 0); + DCHECK_EQ(raw_desc_string[raw_desc->name_offset + raw_desc->name_size - 1], + 0); + desc->name = String(raw_desc_string + raw_desc->name_offset, + raw_desc->name_size - 1); + } else { + desc->name.clear(); + } + if (raw_desc->semantic_offset) { + DCHECK_LE(raw_desc->semantic_offset + raw_desc->semantic_size, + raw_desc->size); + DCHECK_GT(raw_desc->semantic_size, 0); + DCHECK_EQ(raw_desc_string[raw_desc->semantic_offset + + raw_desc->semantic_size - 1], + 0); + desc->semantic = String(raw_desc_string + raw_desc->semantic_offset, + raw_desc->semantic_size - 1); + } else { + desc->semantic.clear(); + } + shm_allocator_->Free(raw_desc); + return true; +} + +void EffectHelper::DestroyEffectParameters( + const std::vector<EffectParamDesc> &descs) { + CommandBufferEntry args[1]; + for (unsigned int i = 0; i < descs.size(); ++i) { + const EffectParamDesc &desc = descs[i]; + args[0].value_uint32 = desc.id; + helper_->AddCommand(DESTROY_PARAM, 1, args); + param_id_allocator_->FreeID(desc.id); + } +} + +} // namespace command_buffer +} // namespace o3d |