static void glEndFragmentShaderATI (void) { GLint errPos; int i; char fragString[4096]; sGeneratingProgram = 0; // header strcpy(fragString, "!!ATIfs1.0\n"); // constants if (sConstString[0] || sConstUsed) { strcat (fragString, "StartConstants;\n"); if (sConstUsed) { for (i = 0; i < 8; i ++) { if (sConst[i] == 1) { char str[128]; sprintf (str, " CONSTANT c%d = program.env[%d];\n", i, i); strcat (fragString, str); } } } if (sConstString[0]) { strcat (fragString, sConstString); } strcat (fragString, "EndConstants;\n\n"); } if (sCurrentPass == 0) { strcat(fragString, "StartOutputPass;\n"); strcat(fragString, sPassString[0]); strcat(fragString, "EndPass;\n"); } else { strcat(fragString, "StartPrelimPass;\n"); strcat(fragString, sPassString[0]); strcat(fragString, "EndPass;\n\n"); strcat(fragString, "StartOutputPass;\n"); strcat(fragString, sPassString[1]); strcat(fragString, "EndPass;\n"); } qglProgramStringARB(GL_TEXT_FRAGMENT_SHADER_ATI, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragString), fragString); qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); if(errPos != -1) { const GLubyte *errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB); common->Warning("WARNING: glError at %d:%s when compiling atiFragmentShader %s", errPos, errString, fragString); } }
/* ================= R_LoadARBProgram ================= */ void R_LoadARBProgram( int progIndex ) { int ofs; int err; idStr fullPath = "glprogs/"; fullPath += progs[progIndex].name; char *fileBuffer; char *buffer; char *start, *end; common->Printf( "%s", fullPath.c_str() ); // load the program even if we don't support it, so // fs_copyfiles can generate cross-platform data dumps fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL ); if ( !fileBuffer ) { common->Printf( ": File not found\n" ); return; } // copy to stack memory and free buffer = (char *)_alloca( strlen( fileBuffer ) + 1 ); strcpy( buffer, fileBuffer ); fileSystem->FreeFile( fileBuffer ); if ( !glConfig.isInitialized ) { return; } // // submit the program string at start to GL // if ( progs[progIndex].ident == 0 ) { // allocate a new identifier for this program progs[progIndex].ident = PROG_USER + progIndex; } // vertex and fragment programs can both be present in a single file, so // scan for the proper header to be the start point, and stamp a 0 in after the end if ( progs[progIndex].target == GL_VERTEX_PROGRAM_ARB ) { if ( !glConfig.ARBVertexProgramAvailable ) { common->Printf( ": GL_VERTEX_PROGRAM_ARB not available\n" ); return; } start = strstr( (char *)buffer, "!!ARBvp" ); } if ( progs[progIndex].target == GL_FRAGMENT_PROGRAM_ARB ) { if ( !glConfig.ARBFragmentProgramAvailable ) { common->Printf( ": GL_FRAGMENT_PROGRAM_ARB not available\n" ); return; } start = strstr( (char *)buffer, "!!ARBfp" ); } if ( !start ) { common->Printf( ": !!ARB not found\n" ); return; } end = strstr( start, "END" ); if ( !end ) { common->Printf( ": END not found\n" ); return; } end[3] = 0; qglBindProgramARB( progs[progIndex].target, progs[progIndex].ident ); qglGetError(); qglProgramStringARB( progs[progIndex].target, GL_PROGRAM_FORMAT_ASCII_ARB, strlen( start ), (unsigned char *)start ); err = qglGetError(); qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, (GLint *)&ofs ); if ( err == GL_INVALID_OPERATION ) { const GLubyte *str = qglGetString( GL_PROGRAM_ERROR_STRING_ARB ); common->Printf( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str ); if ( ofs < 0 ) { common->Printf( "GL_PROGRAM_ERROR_POSITION_ARB < 0 with error\n" ); } else if ( ofs >= (int)strlen( (char *)start ) ) { common->Printf( "error at end of program\n" ); } else { common->Printf( "error at %i:\n%s", ofs, start + ofs ); } return; } if ( ofs != -1 ) { common->Printf( "\nGL_PROGRAM_ERROR_POSITION_ARB != -1 without error\n" ); return; } common->Printf( "\n" ); }