std::string GetOpVecInfo(const OpRcPtrVec & ops) { std::ostringstream os; os << "Size " << ops.size() << std::endl; for(OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i) { os << "Index " << i << " -- " << *ops[i] << std::endl; os << " supportsGPUShader: " << ops[i]->supportsGpuShader() << std::endl; os << " cacheID " << ops[i]->getCacheID() << std::endl; } return os.str(); }
void CreateLut3DOp(OpRcPtrVec & ops, Lut3DRcPtr lut, Interpolation interpolation, TransformDirection direction) { ops.push_back( OpRcPtr(new Lut3DOp(lut, interpolation, direction)) ); }
void FinalizeOpVec(OpRcPtrVec & ops) { for(OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i) { ops[i]->finalize(); } }
int CombineOps(OpRcPtrVec & opVec) { int count = 0; int firstindex = 0; // this must be a signed int OpRcPtrVec tmpops; while(firstindex < static_cast<int>(opVec.size()-1)) { ConstOpRcPtr first = opVec[firstindex]; ConstOpRcPtr second = opVec[firstindex+1]; if(first->canCombineWith(second)) { tmpops.clear(); first->combineWith(tmpops, second); // tmpops may have any number of ops in it. (0, 1, 2, ...) // (size 0 would occur potentially iff the combination // results in a no-op) // // No matter the number, we need to swap them in for the // original ops // Erase the initial two ops we've combined opVec.erase(opVec.begin() + firstindex, opVec.begin() + firstindex + 2); // Insert the new ops (which may be empty) at // this location std::copy(tmpops.begin(), tmpops.end(), std::inserter(opVec, opVec.begin() + firstindex)); // Decrement firstindex by 1, // to backstep and reconsider the A, A' case. // See RemoveInverseOps for the full discussion of // why this is appropriate firstindex = std::max(0, firstindex-1); // We've done something so increment the count! ++count; } else { ++firstindex; } } return count; }
bool IsOpVecNoOp(const OpRcPtrVec & ops) { for(OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i) { if(!ops[i]->isNoOp()) return false; } return true; }
void CreateMatrixOffsetOp(OpRcPtrVec & ops, const float * m44, const float * offset4, TransformDirection direction) { bool mtxIsIdentity = IsM44Identity(m44); bool offsetIsIdentity = IsVecEqualToZero(offset4, 4); if(mtxIsIdentity && offsetIsIdentity) return; ops.push_back( OpRcPtr(new MatrixOffsetOp(m44, offset4, direction)) ); }
void CreateLut1DOp(OpRcPtrVec & ops, const Lut1DRcPtr & lut, Interpolation interpolation, TransformDirection direction) { if(lut->isNoOp()) return; // TODO: Detect if lut1d can be exactly approximated as y = mx + b // If so, return a mtx instead. ops.push_back( OpRcPtr(new Lut1DOp(lut, interpolation, direction)) ); }
std::string SerializeOpVec(const OpRcPtrVec & ops, int indent) { std::ostringstream os; for(OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i) { os << pystring::mul(" ", indent); os << "Op " << i << ": " << *ops[i] << " "; os << ops[i]->getCacheID() << " supports_gpu:" << ops[i]->supportsGpuShader(); os << "\n"; } return os.str(); }
void FinalizeOpVec(OpRcPtrVec & ops, bool optimize) { // TODO: Add envvar to force disable optimizations if(optimize) { OptimizeOpVec(ops); } for(OpRcPtrVec::size_type i = 0, size = ops.size(); i < size; ++i) { ops[i]->finalize(); } }
void CreateIdentityMatrixOp(OpRcPtrVec & ops, TransformDirection direction) { float matrix[16]; memset(matrix, 0, 16 * sizeof(float)); matrix[0] = 1.0f; matrix[5] = 1.0f; matrix[10] = 1.0f; matrix[15] = 1.0f; float offset[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; ops.push_back(MatrixOffsetOpRcPtr(new MatrixOffsetOp(matrix, offset, direction))); }
void BuildLookOps(OpRcPtrVec & ops, ConstColorSpaceRcPtr & currentColorSpace, bool skipColorSpaceConversions, const Config& config, const ConstContextRcPtr & context, const LookParseResult & looks) { const LookParseResult::Options & options = looks.getOptions(); if(options.empty()) { // Do nothing } else if(options.size() == 1) { // As an optimization, if we only have a single look option, // just push back onto the final location RunLookTokens(ops, currentColorSpace, skipColorSpaceConversions, config, context, options[0]); } else { // If we have multiple look options, try each one in order, // and if we can create the ops without a missing file exception, // push back it's results and return bool success = false; std::ostringstream os; OpRcPtrVec tmpOps; ConstColorSpaceRcPtr cs; for(unsigned int i=0; i<options.size(); ++i) { cs = currentColorSpace; tmpOps.clear(); try { RunLookTokens(tmpOps, cs, skipColorSpaceConversions, config, context, options[i]); success = true; break; } catch(ExceptionMissingFile & e) { if(i != 0) os << " ... "; os << "("; LookParseResult::serialize(os, options[i]); os << ") " << e.what(); } } if(success) { currentColorSpace = cs; std::copy(tmpOps.begin(), tmpOps.end(), std::back_inserter(ops)); } else { throw ExceptionMissingFile(os.str().c_str()); } } }