void cub_XmlAttribute_forEach(const char *attributes, cub_XmlAttributeCallback callback) { char *buffer = strcpy(malloc(strlen(attributes) + 1), attributes); char *ptr = buffer; Attribute a = {0}; while (extractAttributes(&ptr, &a)) if(!callback(a.name, a.value)) break; free(buffer); }
//----------------------------------------------------------------------- void GLSLLinkProgram::activate(void) { if (!mLinked) { if (mVertexProgram) { // Some drivers (e.g. OS X on nvidia) incorrectly determine the attribute binding automatically // and end up aliasing existing built-ins. So avoid! // Bind all used attribs - not all possible ones otherwise we'll get // lots of warnings in the log, and also may end up aliasing names used // as varyings by accident // Because we can't ask GL whether an attribute is used in the shader // until it is linked (chicken and egg!) we have to parse the source size_t numAttribs = sizeof(msCustomAttributes)/sizeof(CustomAttribute); const String& vpSource = mVertexProgram->getGLSLProgram()->getSource(); for (size_t i = 0; i < numAttribs; ++i) { const CustomAttribute& a = msCustomAttributes[i]; // we're looking for either: // attribute vec<n> <semantic_name> // in vec<n> <semantic_name> // The latter is recommended in GLSL 1.3 onwards // be slightly flexible about formatting String::size_type pos = vpSource.find(a.name); if (pos != String::npos) { String::size_type startpos = vpSource.find("attribute", pos < 20 ? 0 : pos-20); if (startpos == String::npos) startpos = vpSource.find("in", pos-20); if (startpos != String::npos && startpos < pos) { // final check String expr = vpSource.substr(startpos, pos + a.name.length() - startpos); StringVector vec = StringUtil::split(expr); if ((vec[0] == "in" || vec[0] == "attribute") && vec[2] == a.name) glBindAttribLocationARB(mGLHandle, a.attrib, a.name.c_str()); } } } } if (mGeometryProgram) { RenderOperation::OperationType inputOperationType = mGeometryProgram->getGLSLProgram()->getInputOperationType(); glProgramParameteriEXT(mGLHandle,GL_GEOMETRY_INPUT_TYPE_EXT, getGLGeometryInputPrimitiveType(inputOperationType, mGeometryProgram->isAdjacencyInfoRequired())); RenderOperation::OperationType outputOperationType = mGeometryProgram->getGLSLProgram()->getOutputOperationType(); switch (outputOperationType) { case RenderOperation::OT_POINT_LIST: case RenderOperation::OT_LINE_STRIP: case RenderOperation::OT_TRIANGLE_STRIP: case RenderOperation::OT_LINE_LIST: case RenderOperation::OT_TRIANGLE_LIST: case RenderOperation::OT_TRIANGLE_FAN: break; } glProgramParameteriEXT(mGLHandle,GL_GEOMETRY_OUTPUT_TYPE_EXT, getGLGeometryOutputPrimitiveType(outputOperationType)); glProgramParameteriEXT(mGLHandle,GL_GEOMETRY_VERTICES_OUT_EXT, mGeometryProgram->getGLSLProgram()->getMaxOutputVertices()); } glLinkProgramARB( mGLHandle ); glGetObjectParameterivARB( mGLHandle, GL_OBJECT_LINK_STATUS_ARB, &mLinked ); // force logging and raise exception if not linked checkForGLSLError( "GLSLLinkProgram::Activate", "Error linking GLSL Program Object : ", mGLHandle, !mLinked, !mLinked ); if(mLinked) { logObjectInfo( String("GLSL link result : "), mGLHandle ); buildGLUniformReferences(); extractAttributes(); } } if (mLinked) { checkForGLSLError( "GLSLLinkProgram::Activate", "Error prior to using GLSL Program Object : ", mGLHandle, false, false); glUseProgramObjectARB( mGLHandle ); checkForGLSLError( "GLSLLinkProgram::Activate", "Error using GLSL Program Object : ", mGLHandle, false, false); } }