void Shader::link() { for( int i = 0; i < mSeparatedTransformFeedbackVarying.size(); i++ ){ const char *attrib[] = { mSeparatedTransformFeedbackVarying[i].c_str() }; glTransformFeedbackVaryingsEXT( getHandle(), 1, attrib, GL_SEPARATE_ATTRIBS_EXT ); } if( mInterleavedTransformFeedbackVarying.size() ){ const char* attribs[mInterleavedTransformFeedbackVarying.size()]; for( int i = 0; i < mInterleavedTransformFeedbackVarying.size(); i++ ){ attribs[i] = mInterleavedTransformFeedbackVarying[i].c_str(); } glTransformFeedbackVaryingsEXT( getHandle(), mInterleavedTransformFeedbackVarying.size(), attribs, GL_INTERLEAVED_ATTRIBS_EXT ); } glLinkProgram( mObj->mHandle ); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_EXTTransformFeedback_nglTransformFeedbackVaryingsEXT(JNIEnv *env, jclass clazz, jint program, jint count, jobject varyings, jint varyings_position, jint bufferMode, jlong function_pointer) { const GLchar *varyings_address = ((const GLchar *)(*env)->GetDirectBufferAddress(env, varyings)) + varyings_position; unsigned int _str_i; GLchar *_str_address; GLchar **varyings_str = (GLchar **) malloc(count * sizeof(GLchar *)); glTransformFeedbackVaryingsEXTPROC glTransformFeedbackVaryingsEXT = (glTransformFeedbackVaryingsEXTPROC)((intptr_t)function_pointer); _str_i = 0; _str_address = (GLchar *)varyings_address; while ( _str_i < count ) { varyings_str[_str_i++] = _str_address; _str_address += strlen(_str_address) + 1; } glTransformFeedbackVaryingsEXT(program, count, (const GLchar **)varyings_str, bufferMode); free(varyings_str); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_EXTTransformFeedback_nglTransformFeedbackVaryingsEXT(JNIEnv *__env, jclass clazz, jint program, jint count, jlong varyingsAddress, jint bufferMode) { glTransformFeedbackVaryingsEXTPROC glTransformFeedbackVaryingsEXT = (glTransformFeedbackVaryingsEXTPROC)tlsGetFunction(1830); intptr_t varyings = (intptr_t)varyingsAddress; UNUSED_PARAM(clazz) glTransformFeedbackVaryingsEXT(program, count, varyings, bufferMode); }
WSProgram* WCShaderManager::ParseProgram(xercesc::DOMElement *element, const bool &verbose) { char *tmpChars; std::string tmpStr; //Create program object WSProgram *program = new WSProgram(); program->_id = glCreateProgram(); //Get the program name program->_name = WCSerializeableObject::GetStringAttrib(element, "name"); //Process all shaders xercesc::DOMNode *tmpNode; std::map<std::string,WSShader*>::iterator iter; XMLCh *xmlString = xercesc::XMLString::transcode("shader"); xercesc::DOMNodeList *nodeList = element->getElementsByTagName(xmlString); xercesc::XMLString::release(&xmlString); int numShaders = nodeList->getLength(); xercesc::DOMElement *tmpElement; //Loop through all shaders and process for (int index=0; index < numShaders; index++) { tmpElement = (xercesc::DOMElement*)nodeList->item(index); //Get the value node tmpNode = tmpElement->getFirstChild(); //Find the shader name tmpChars = xercesc::XMLString::transcode(tmpNode->getNodeValue()); tmpStr = std::string(tmpChars); xercesc::XMLString::release(&tmpChars); //Look up in map iter = this->_shaderMap.find(tmpStr); //Is a shader found at all if (iter == this->_shaderMap.end()) { CLOGGER_ERROR(WCLogManager::RootLogger(), "WCShaderManager::ParseProgram - " << tmpStr << " not found."); delete program; return NULL; } //Is the shader valid if ((*iter).second->_id == 0) { CLOGGER_INFO(WCLogManager::RootLogger(), "WCShaderManager::ParseProgram - " << tmpStr << " requires excluding this program."); delete program; return NULL; } //Attach shader glAttachShader(program->_id, (*iter).second->_id); //Add shader to shader list program->_shaders.push_back( (*iter).second ); } //Process transform feedback xmlString = xercesc::XMLString::transcode("transform_feedback"); nodeList = element->getElementsByTagName(xmlString); xercesc::XMLString::release(&xmlString); if (nodeList->getLength() == 1) { //Found a transform feedback tmpElement = (xercesc::DOMElement*)nodeList->item(0); //Get type attribute std::string typeStr = WCSerializeableObject::GetStringAttrib(tmpElement, "type"); GLenum type; //Convert string to enum if (typeStr == "GL_INTERLEAVED_ATTRIBS_EXT") type = GL_INTERLEAVED_ATTRIBS_EXT; else if (typeStr == "GL_SEPARATE_ATTRIBS_EXT") type = GL_SEPARATE_ATTRIBS_EXT; else { CLOGGER_ERROR(WCLogManager::RootLogger(), "WCShaderManager::ParseProgram - Unknown transform feedback type(" << typeStr << "."); delete program; return NULL; } //Get list of varyings xmlString = xercesc::XMLString::transcode("varying"); nodeList = tmpElement->getElementsByTagName(xmlString); xercesc::XMLString::release(&xmlString); GLint varyingCount = nodeList->getLength(); const GLchar** varyings = new const GLchar*[varyingCount]; //Process varyings for (int index=0; index<varyingCount; index++) { //Get the varying element tmpElement = (xercesc::DOMElement*)nodeList->item(index); //Get the value node tmpNode = tmpElement->getFirstChild(); //Get the name of the varying and put into array varyings[index] = xercesc::XMLString::transcode(tmpNode->getNodeValue()); } //Set up the transform feedback for the program glTransformFeedbackVaryingsEXT(program->_id, varyingCount, varyings, type); //Delete all of the varyings for (int j=0; j<varyingCount; j++) { //Do null value check if (varyings[j]) delete varyings[j]; } //Delete the array if (varyings) delete varyings; } //Process geometry shader params (if present) xmlString = xercesc::XMLString::transcode("geometry_shader"); nodeList = element->getElementsByTagName(xmlString); xercesc::XMLString::release(&xmlString); if (nodeList->getLength() == 1) { //Found a geometry shader tmpElement = (xercesc::DOMElement*)nodeList->item(0); //Get input type std::string inputTypeStr = WCSerializeableObject::GetStringAttrib(tmpElement, "inputType"); std::string outputTypeStr = WCSerializeableObject::GetStringAttrib(tmpElement, "outputType"); GLint vertexOut = (GLint)WCSerializeableObject::GetFloatAttrib(tmpElement, "vertsOut"); //Set the attributes GLenum inputType = ConvertGLTypeStringToEnum(inputTypeStr); GLenum outputType = ConvertGLTypeStringToEnum(outputTypeStr); //Set the program parameters glProgramParameteriEXT(program->_id, GL_GEOMETRY_INPUT_TYPE_EXT, inputType); glProgramParameteriEXT(program->_id, GL_GEOMETRY_VERTICES_OUT_EXT, vertexOut); glProgramParameteriEXT(program->_id, GL_GEOMETRY_OUTPUT_TYPE_EXT, outputType); } //Link the program glLinkProgram(program->_id); GLint linked; glGetProgramiv(program->_id, GL_OBJECT_LINK_STATUS_ARB, &linked); //Check the link status if (!linked) { char temp[256] = ""; //If not, print out compilation errors glGetProgramInfoLog(program->_id, 256, NULL, temp); CLOGGER_WARN(WCLogManager::RootLogger(), "WCShaderManager::ParseProgram - Program Link failed:\n" << temp); delete program; program = NULL; } else { if (verbose) CLOGGER_DEBUG(WCLogManager::RootLogger(), "Program " << program->_id << " successfully linked: " << program->_name); } //Return the program object return program; }