00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #define _GNU_SOURCE
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include <glh/glh_extensions.h>
00021 #if defined WIN32
00022 #include <io.h>
00023 #include <direct.h>
00024 #else
00025 #include <unistd.h>
00026 #include <dirent.h>
00027 #endif
00028
00029 #include <fcntl.h>
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032
00033 #include "arbprogram.h"
00034 #include "tools.h"
00035 #include "sysconf.h"
00036
00037
00038 #define VP_HEADER "!!ARBvp"
00039 #define FP_HEADER "!!ARBfp"
00040
00041 #define TEXTURE_MARKER "#!"
00042
00043 static int arbpCompare(const void *p1, const void *p2)
00044 {
00045 ARBProgram *fp1, *fp2;
00046
00047 fp1 = (ARBProgram *)p1;
00048 fp2 = (ARBProgram *)p2;
00049
00050 return strcmp(fp1->filename, fp2->filename);
00051 }
00052
00053 static int loadProgram(ARBProgram *prog, int numTextures, Texture *textures)
00054 {
00055 const GLubyte *error_string;
00056 TextureObject *textureObject;
00057 int i, textureUnit, found;
00058 char textureName[256];
00059 GLint error_pos;
00060 char *cp;
00061
00062 if (strstr(prog->prog, VP_HEADER) == prog->prog) {
00063 prog->programType = GL_VERTEX_SHADER;
00064 } else if (strstr(prog->prog, FP_HEADER) == prog->prog) {
00065 prog->programType = GL_FRAGMENT_SHADER;
00066 } else {
00067 fprintf(stderr, "unknown program type\n");
00068 exit(1);
00069 }
00070
00071 prog->numTextureObjects = 0;
00072 prog->textureObjects = NULL;
00073
00074 cp = prog->prog;
00075 while (*cp) {
00076 while (*cp && *cp != '\n' && *cp != '\r') {
00077 cp++;
00078 }
00079 if (*cp && (*cp == '\n' || *cp == '\r')) {
00080 cp++;
00081 }
00082 if (strstr(cp, TEXTURE_MARKER) == cp) {
00083 cp += 2;
00084 if (sscanf(cp, "%s=", textureName) != 1) {
00085 fprintf(stderr, "parse error in file %s\n",
00086 prog->filename);
00087 exit(1);
00088 }
00089 cp = strchr(cp, '=') + 1;
00090 if (sscanf(cp, "%i", &textureUnit) != 1) {
00091 fprintf(stderr, "parse error in file %s: %s\n",
00092 prog->filename, cp);
00093 exit(1);
00094 }
00095 prog->numTextureObjects++;
00096 if (! (prog->textureObjects = (TextureObject *)realloc(
00097 prog->textureObjects,
00098 prog->numTextureObjects *
00099 sizeof(TextureObject)))) {
00100 fprintf(stderr, "not enough memory for texture objects\n");
00101 exit(1);
00102 }
00103 textureObject = &prog->textureObjects[prog->numTextureObjects - 1];
00104 textureObject->texUnit = textureUnit;
00105
00106 found = 0;
00107 for (i = 0; i < numTextures; i++) {
00108 if (! strcmp(textureName, textures[i].name)) {
00109 textureObject->texture = textures[i];
00110 found = 1;
00111 break;
00112 }
00113 }
00114 if (! found) {
00115 fprintf(stderr, "invalid texture name '%s' in program %s\n",
00116 textureName, prog->filename);
00117 exit(1);
00118 }
00119 }
00120 }
00121
00122 glEnable(prog->programType);
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 glDisable(prog->programType);
00138
00139 return 1;
00140 }
00141
00142 ARBProgram loadARBProg(const char *filename, int numTextures, Texture *textures)
00143 {
00144 ARBProgram prog;
00145 int fd;
00146 struct stat statbuf;
00147 char *fnp;
00148
00149 if (! (fnp = strrchr(filename, DIR_SEP))) {
00150 fnp = (char *) filename;
00151 } else {
00152 fnp++;
00153 }
00154
00155 if (! (prog.filename = strdup(fnp))) {
00156 fprintf(stderr, "cannot duplicate filename\n");
00157 exit(1);
00158 }
00159
00160 #if defined WIN32
00161 if ((fd = open(filename, O_RDONLY | O_BINARY)) < 0) {
00162 #else
00163 if ((fd = open(filename, O_RDONLY)) < 0) {
00164 #endif
00165 perror("opening file failed");
00166 exit(1);
00167 }
00168
00169 if (fstat(fd, &statbuf) < 0) {
00170 fprintf(stderr, "failed to get file stats of %s\n",
00171 filename);
00172 }
00173
00174 prog.size = statbuf.st_size;
00175
00176 if (! (prog.prog = (char *)malloc(prog.size + 1))) {
00177 fprintf(stderr, "not enough memory for "
00178 "program\n");
00179 exit(1);
00180 }
00181
00182 if (read(fd, prog.prog, prog.size) != prog.size) {
00183 fprintf(stderr, "reading file %s failed\n",
00184 prog.filename);
00185 exit(1);
00186 }
00187 prog.prog[prog.size] = '\0';
00188
00189 if (! loadProgram(&prog, numTextures, textures)) {
00190 fprintf(stderr, "exiting due to parse error in program "
00191 "'%s'\n", prog.filename);
00192 exit(1);
00193 }
00194 close(fd);
00195
00196 return prog;
00197 }
00198
00199 #if ! defined WIN32
00200 void loadARBProgs(char *directory, char *extension,
00201 int numTextures, Texture *textures,
00202 int *numProgs, ARBProgram **progs)
00203 {
00204 ARBProgram *prog;
00205 struct dirent *entry;
00206 struct stat statbuf;
00207 DIR *dp;
00208 char *file;
00209
00210 *numProgs = 0;
00211 *progs = NULL;
00212
00213 fprintf(stderr, "\nloading programs ...\n");
00214
00215 if ((dp = opendir(directory)) == NULL) {
00216 fprintf(stderr, "cannot open current directory\n");
00217 return;
00218 }
00219
00220 while((entry = readdir(dp))) {
00221 if (! (file = (char *)malloc(strlen(directory) + strlen(entry->d_name) + 2))) {
00222 fprintf(stderr, "not enough memory for file template\n");
00223 exit(1);
00224 }
00225 strcpy(file, directory);
00226 if (!endsWith(directory, "/")) {
00227 strcat(file, "/");
00228 }
00229 strcat(file, entry->d_name);
00230 lstat(file, &statbuf);
00231 if (S_ISREG(statbuf.st_mode)) {
00232 if (endsWith(entry->d_name, extension)) {
00233 (*numProgs)++;
00234 if (! (*progs = (ARBProgram *)realloc(*progs,
00235 *numProgs * sizeof(ARBProgram)))) {
00236 fprintf(stderr, "not enough memory for "
00237 "program structures\n");
00238 exit(1);
00239 }
00240 prog = &(*progs)[*numProgs - 1];
00241
00242 *prog = loadARBProg(file, numTextures, textures);
00243 }
00244 }
00245 free(file);
00246 }
00247 closedir(dp);
00248
00249 if (! *numProgs) {
00250 fprintf(stderr, "no programs found\n");
00251 exit(1);
00252 }
00253
00254 fprintf(stderr, "\n");
00255
00256
00257
00258 qsort(*progs, *numProgs, sizeof(ARBProgram), arbpCompare);
00259 }
00260 #else
00261 void loadARBProgs(char *directory, char *extension,
00262 int numTextures, Texture *textures,
00263 int *numProgs, ARBProgram **progs)
00264 {
00265 struct _finddata_t fd;
00266 ARBProgram *prog;
00267 char *files, *cwd;
00268 intptr_t handle;
00269
00270 *numProgs = 0;
00271 *progs = NULL;
00272
00273 fprintf(stderr, "\nloading programs ...\n");
00274
00275 if (endsWith(directory, "\\")) {
00276 directory[strlen(directory) - 1] = '\0';
00277 }
00278
00279 if (! (files = (char *)malloc(strlen(directory) + 3 +
00280 strlen(extension)))) {
00281 fprintf(stderr, "not enough memory for file template\n");
00282 exit(1);
00283 }
00284 if (!(cwd = _getcwd(NULL, 256))) {
00285 fprintf(stderr, "Failed to get current working directory\n");
00286 exit(1);
00287 }
00288 if (_chdir(directory) != 0) {
00289 fprintf(stderr, "directory '%s' not found\n", directory);
00290 }
00291 sprintf(files, ".\\*%s", extension);
00292 if ((handle = _findfirst(files, &fd)) == -1) {
00293 fprintf(stderr, "no programs found in %s\n", files);
00294 return;
00295 }
00296
00297 free(files);
00298
00299 do {
00300 (*numProgs)++;
00301 if (! (*progs = (ARBProgram *)realloc(*progs,
00302 *numProgs * sizeof(ARBProgram)))) {
00303 fprintf(stderr, "not enough memory for "
00304 "program structures\n");
00305 exit(1);
00306 }
00307 prog = &(*progs)[*numProgs - 1];
00308
00309 *prog = loadARBProg(fd.name, numTextures, textures);
00310 } while(! _findnext(handle, &fd));
00311
00312 if (! *numProgs) {
00313 fprintf(stderr, "no programs found\n");
00314 exit(1);
00315 }
00316
00317
00318 if (_chdir(cwd) != 0) {
00319 fprintf(stderr, "Failed to restore working directory\n");
00320 exit(1);
00321 }
00322 free(cwd);
00323
00324 fprintf(stderr, "\n");
00325
00326
00327
00328 qsort(*progs, *numProgs, sizeof(ARBProgram), arbpCompare);
00329 }
00330 #endif
00331
00332 void activateARBProg(ARBProgram *prog)
00333 {
00334 texActivate(prog->numTextureObjects, prog->textureObjects);
00335 glEnable(prog->programType);
00336 glBindProgramARB(prog->programType, prog->id);
00337 }
00338
00339 void deactivateARBProg(ARBProgram *prog)
00340 {
00341 texDeactivate(prog->numTextureObjects, prog->textureObjects);
00342 glDisable(prog->programType);
00343 glBindProgramARB(prog->programType, 0);
00344 }