00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "pandabase.h"
00017 #include "shader.h"
00018 #include "preparedGraphicsObjects.h"
00019 #include "virtualFileSystem.h"
00020
00021 #ifdef HAVE_CG
00022 #include "Cg/cg.h"
00023 #define JCG_PROFILE_GLSLV ((CGprofile)7007)
00024 #define JCG_PROFILE_GLSLF ((CGprofile)7008)
00025 #endif
00026
00027 TypeHandle Shader::_type_handle;
00028 Shader::ShaderTable Shader::_load_table;
00029 Shader::ShaderTable Shader::_make_table;
00030 Shader::ShaderCaps Shader::_default_caps;
00031 int Shader::_shaders_generated;
00032 ShaderUtilization Shader::_shader_utilization = SUT_unspecified;
00033
00034
00035
00036
00037
00038
00039
00040 void Shader::
00041 cp_report_error(ShaderArgInfo &p, const string &msg) {
00042
00043 string vstr;
00044 if (p._varying) {
00045 vstr = "varying ";
00046 } else {
00047 vstr = "uniform ";
00048 }
00049
00050 string dstr = "unknown ";
00051 if (p._direction == SAD_in) {
00052 dstr = "in ";
00053 } else if (p._direction == SAD_out) {
00054 dstr = "out ";
00055 } else if (p._direction == SAD_inout) {
00056 dstr = "inout ";
00057 }
00058
00059 string tstr = "invalid ";
00060 switch (p._type) {
00061 case SAT_scalar: tstr = "scalar "; break;
00062 case SAT_vec1: tstr = "vec1 "; break;
00063 case SAT_vec2: tstr = "vec2 "; break;
00064 case SAT_vec3: tstr = "vec3 "; break;
00065 case SAT_vec4: tstr = "vec4 "; break;
00066 case SAT_mat1x1: tstr = "mat1x1 "; break;
00067 case SAT_mat1x2: tstr = "mat1x2 "; break;
00068 case SAT_mat1x3: tstr = "mat1x3 "; break;
00069 case SAT_mat1x4: tstr = "mat1x4 "; break;
00070 case SAT_mat2x1: tstr = "mat2x1 "; break;
00071 case SAT_mat2x2: tstr = "mat2x2 "; break;
00072 case SAT_mat2x3: tstr = "mat2x3 "; break;
00073 case SAT_mat2x4: tstr = "mat2x4 "; break;
00074 case SAT_mat3x1: tstr = "mat3x1 "; break;
00075 case SAT_mat3x2: tstr = "mat3x2 "; break;
00076 case SAT_mat3x3: tstr = "mat3x3 "; break;
00077 case SAT_mat3x4: tstr = "mat3x4 "; break;
00078 case SAT_mat4x1: tstr = "mat4x1 "; break;
00079 case SAT_mat4x2: tstr = "mat4x2 "; break;
00080 case SAT_mat4x3: tstr = "mat4x3 "; break;
00081 case SAT_mat4x4: tstr = "mat4x4 "; break;
00082 case SAT_sampler1d: tstr = "sampler1d "; break;
00083 case SAT_sampler2d: tstr = "sampler2d "; break;
00084 case SAT_sampler3d: tstr = "sampler3d "; break;
00085 case SAT_sampler2dArray: tstr = "sampler2dArray "; break;
00086 case SAT_samplercube: tstr = "samplercube "; break;
00087 default: tstr = "unknown "; break;
00088 }
00089
00090 string cstr = "invalid";
00091 switch (p._class) {
00092 case SAC_scalar: cstr = "scalar "; break;
00093 case SAC_vector: cstr = "vector "; break;
00094 case SAC_matrix: cstr = "matrix "; break;
00095 case SAC_sampler: cstr = "sampler "; break;
00096 case SAC_array: cstr = "array "; break;
00097 default: cstr = "unknown "; break;
00098 }
00099
00100 Filename fn = get_filename(p._id._type);
00101 p._cat->error() << fn << ": " << vstr << dstr << tstr <<
00102 p._id._name << ": " << msg << "\n";
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112 bool Shader::
00113 cp_errchk_parameter_words(ShaderArgInfo &p, int len)
00114 {
00115 vector_string words;
00116 tokenize(p._id._name, words, "_");
00117 if ((int)words.size() != len) {
00118 cp_report_error(p, "parameter name has wrong number of words");
00119 return false;
00120 }
00121 return true;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131 bool Shader::
00132 cp_errchk_parameter_in(ShaderArgInfo &p)
00133 {
00134 if (p._direction != SAD_in) {
00135 cp_report_error(p, "parameter should be declared 'in'");
00136 return false;
00137 }
00138 return true;
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148 bool Shader::
00149 cp_errchk_parameter_varying(ShaderArgInfo &p)
00150 {
00151 if (!p._varying) {
00152 cp_report_error(p, "parameter should be declared 'varying'");
00153 return false;
00154 }
00155 return true;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165 bool Shader::
00166 cp_errchk_parameter_uniform(ShaderArgInfo &p)
00167 {
00168 if (p._varying) {
00169 cp_report_error(p, "parameter should be declared 'uniform'");
00170 return false;
00171 }
00172 return true;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182 bool Shader::
00183 cp_errchk_parameter_float(ShaderArgInfo &p, int lo, int hi)
00184 {
00185 int nfloat;
00186 switch (p._type) {
00187 case SAT_scalar: nfloat = 1; break;
00188 case SAT_vec2: nfloat = 2; break;
00189 case SAT_vec3: nfloat = 3; break;
00190 case SAT_vec4: nfloat = 4; break;
00191 case SAT_mat4x4: nfloat = 16; break;
00192 default: nfloat = 0; break;
00193 }
00194 if ((nfloat < lo)||(nfloat > hi)) {
00195 string msg = "wrong type for parameter:";
00196 cp_report_error(p, msg);
00197 return false;
00198 }
00199 return true;
00200 }
00201
00202
00203
00204
00205
00206
00207 bool Shader::
00208 cp_errchk_parameter_ptr(ShaderArgInfo &p) {
00209 switch (p._class) {
00210 case SAC_scalar: return true;
00211 case SAC_vector: return true;
00212 case SAC_matrix: return true;
00213 case SAC_array:
00214 switch (p._subclass){
00215 case SAC_scalar: return true;
00216 case SAC_vector: return true;
00217 case SAC_matrix: return true;
00218 default:
00219 string msg = "unsupported array subclass.";
00220 cp_report_error(p,msg);
00221 return false;
00222 }
00223 default:
00224 string msg = "unsupported class.";
00225 cp_report_error(p,msg);
00226 return false;
00227 }
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237 bool Shader::
00238 cp_errchk_parameter_sampler(ShaderArgInfo &p)
00239 {
00240 if ((p._type!=SAT_sampler1d)&&
00241 (p._type!=SAT_sampler2d)&&
00242 (p._type!=SAT_sampler3d)&&
00243 (p._type!=SAT_sampler2dArray)&&
00244 (p._type!=SAT_samplercube)) {
00245 cp_report_error(p, "parameter should have a 'sampler' type");
00246 return false;
00247 }
00248 return true;
00249 }
00250
00251
00252
00253
00254
00255
00256 bool Shader::
00257 cp_parse_eol(ShaderArgInfo &p, vector_string &words, int &next) {
00258 if (words[next] != "") {
00259 cp_report_error(p, "Too many words in parameter");
00260 return false;
00261 }
00262 return true;
00263 }
00264
00265
00266
00267
00268
00269
00270 bool Shader::
00271 cp_parse_delimiter(ShaderArgInfo &p, vector_string &words, int &next) {
00272 if ((words[next] != "to")&&(words[next] != "rel")) {
00273 cp_report_error(p, "Keyword 'to' or 'rel' expected");
00274 return false;
00275 }
00276 next += 1;
00277 return true;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286 string Shader::
00287 cp_parse_non_delimiter(vector_string &words, int &next) {
00288 const string &nword = words[next];
00289 if ((nword == "")||(nword == "to")||(nword == "rel")) {
00290 return "";
00291 }
00292 next += 1;
00293 return nword;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 bool Shader::
00303 cp_parse_coord_sys(ShaderArgInfo &p,
00304 vector_string &pieces, int &next,
00305 ShaderMatSpec &bind, bool fromflag) {
00306
00307 string word1 = cp_parse_non_delimiter(pieces, next);
00308 if (pieces[next] == "of") next++;
00309 string word2 = cp_parse_non_delimiter(pieces, next);
00310
00311 ShaderMatInput from_single;
00312 ShaderMatInput from_double;
00313 ShaderMatInput to_single;
00314 ShaderMatInput to_double;
00315
00316 if (word1 == "") {
00317 cp_report_error(p, "Could not parse coordinate system name");
00318 return false;
00319 } else if (word1 == "world") {
00320 from_single = SMO_world_to_view;
00321 from_double = SMO_INVALID;
00322 to_single = SMO_view_to_world;
00323 to_double = SMO_INVALID;
00324 } else if (word1 == "model") {
00325 from_single = SMO_model_to_view;
00326 from_double = SMO_view_x_to_view;
00327 to_single = SMO_view_to_model;
00328 to_double = SMO_view_to_view_x;
00329 } else if (word1 == "clip") {
00330 from_single = SMO_clip_to_view;
00331 from_double = SMO_clip_x_to_view;
00332 to_single = SMO_view_to_clip;
00333 to_double = SMO_view_to_clip_x;
00334 } else if (word1 == "view") {
00335 from_single = SMO_identity;
00336 from_double = SMO_view_x_to_view;
00337 to_single = SMO_identity;
00338 to_double = SMO_view_to_view_x;
00339 } else if (word1 == "apiview") {
00340 from_single = SMO_apiview_to_view;
00341 from_double = SMO_apiview_x_to_view;
00342 to_single = SMO_view_to_apiview;
00343 to_double = SMO_view_to_apiview_x;
00344 } else if (word1 == "apiclip") {
00345 from_single = SMO_apiclip_to_view;
00346 from_double = SMO_apiclip_x_to_view;
00347 to_single = SMO_view_to_apiclip;
00348 to_double = SMO_view_to_apiclip_x;
00349 } else {
00350 from_single = SMO_view_x_to_view;
00351 from_double = SMO_view_x_to_view;
00352 to_single = SMO_view_to_view_x;
00353 to_double = SMO_view_to_view_x;
00354 word2 = word1;
00355 }
00356
00357 if (fromflag) {
00358 if (word2 == "") {
00359 bind._part[0] = from_single;
00360 bind._arg[0] = NULL;
00361 } else {
00362 if (from_double == SMO_INVALID) {
00363 cp_report_error(p, "Could not parse coordinate system name");
00364 return false;
00365 }
00366 bind._part[0] = from_double;
00367 bind._arg[0] = InternalName::make(word2);
00368 }
00369 } else {
00370 if (word2 == "") {
00371 bind._part[1] = to_single;
00372 bind._arg[1] = NULL;
00373 } else {
00374 if (to_double == SMO_INVALID) {
00375 cp_report_error(p, "Could not parse coordinate system name");
00376 return false;
00377 }
00378 bind._part[1] = to_double;
00379 bind._arg[1] = InternalName::make(word2);
00380 }
00381 }
00382 return true;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392 int Shader::
00393 cp_dependency(ShaderMatInput inp) {
00394
00395 int dep = SSD_general;
00396
00397 if (inp == SMO_INVALID) {
00398 return SSD_NONE;
00399 }
00400 if (inp == SMO_attr_material) {
00401 dep |= SSD_material;
00402 }
00403 if (inp == SMO_attr_color) {
00404 dep |= SSD_color;
00405 }
00406 if (inp == SMO_attr_colorscale) {
00407 dep |= SSD_colorscale;
00408 }
00409 if (inp == SMO_attr_fog || inp == SMO_attr_fogcolor) {
00410 dep |= SSD_fog;
00411 }
00412 if ((inp == SMO_model_to_view)||
00413 (inp == SMO_view_to_model)) {
00414 dep |= SSD_transform;
00415 }
00416 if ((inp == SMO_texpad_x)||
00417 (inp == SMO_texpix_x)||
00418 (inp == SMO_alight_x)||
00419 (inp == SMO_dlight_x)||
00420 (inp == SMO_plight_x)||
00421 (inp == SMO_slight_x)||
00422 (inp == SMO_satten_x)||
00423 (inp == SMO_mat_constant_x)||
00424 (inp == SMO_vec_constant_x)||
00425 (inp == SMO_clipplane_x)||
00426 (inp == SMO_view_x_to_view)||
00427 (inp == SMO_view_to_view_x)||
00428 (inp == SMO_apiview_x_to_view)||
00429 (inp == SMO_view_to_apiview_x)||
00430 (inp == SMO_clip_x_to_view)||
00431 (inp == SMO_view_to_clip_x)||
00432 (inp == SMO_apiclip_x_to_view)||
00433 (inp == SMO_view_to_apiclip_x)) {
00434 dep |= SSD_shaderinputs;
00435 }
00436
00437 return dep;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 void Shader::
00450 cp_optimize_mat_spec(ShaderMatSpec &spec) {
00451
00452
00453
00454 if (spec._func == SMF_first) {
00455 spec._part[1] = SMO_INVALID;
00456 spec._arg[1] = 0;
00457 }
00458 if (spec._func == SMF_compose) {
00459 if (spec._part[1] == SMO_identity) {
00460 spec._func = SMF_first;
00461 }
00462 }
00463 if (spec._func == SMF_compose) {
00464 if (spec._part[0] == SMO_identity) {
00465 spec._func = SMF_first;
00466 spec._part[0] = spec._part[1];
00467 spec._arg[0] = spec._arg[1];
00468 }
00469 }
00470
00471
00472
00473 spec._dep[0] = cp_dependency(spec._part[0]);
00474 spec._dep[1] = cp_dependency(spec._part[1]);
00475 }
00476
00477 #ifdef HAVE_CG
00478
00479
00480
00481
00482
00483 void Shader::cg_recurse_parameters(CGparameter parameter,
00484 const ShaderType& type, bool& success) {
00485
00486 if (parameter == 0)
00487 return;
00488
00489 do {
00490 int arg_dim[] = {1,0,0};
00491 ShaderArgDir arg_dir = cg_parameter_dir(parameter);
00492 ShaderArgType arg_type = cg_parameter_type(parameter);
00493 ShaderArgClass arg_class = cg_parameter_class(parameter);
00494 ShaderArgClass arg_subclass = arg_class;
00495
00496 CGenum vbl = cgGetParameterVariability(parameter);
00497
00498 if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)){
00499 switch (cgGetParameterType(parameter)) {
00500 case CG_STRUCT:
00501 cg_recurse_parameters(
00502 cgGetFirstStructParameter(parameter),type,success); break;
00503
00504 case CG_ARRAY:
00505 arg_type = cg_parameter_type(cgGetFirstStructParameter(parameter));
00506 arg_subclass = cg_parameter_class(cgGetFirstStructParameter(parameter));
00507
00508 arg_dim[0] = cgGetArraySize(parameter,0);
00509
00510
00511
00512
00513
00514 default:{
00515 arg_dim[1] = cgGetParameterRows(parameter);
00516 arg_dim[2] = cgGetParameterColumns(parameter);
00517
00518 ShaderArgId id;
00519 id._name = cgGetParameterName(parameter);
00520 id._type = type;
00521 id._seqno = -1;
00522 success &= compile_parameter(id, arg_class, arg_subclass, arg_type,
00523 arg_dir, (vbl == CG_VARYING), arg_dim, gobj_cat.get_safe_ptr()); break;
00524 }
00525 }
00526 }
00527 } while((parameter = cgGetNextParameter(parameter))!= 0);
00528 }
00529 #endif // HAVE_CG
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 bool Shader::
00543 compile_parameter(const ShaderArgId &arg_id,
00544 const ShaderArgClass &arg_class,
00545 const ShaderArgClass &arg_subclass,
00546 const ShaderArgType &arg_type,
00547 const ShaderArgDir &arg_direction,
00548 bool arg_varying,
00549 int *arg_dim,
00550 NotifyCategory *arg_cat)
00551 {
00552 ShaderArgInfo p;
00553 p._id = arg_id;
00554 p._class = arg_class;
00555 p._subclass = arg_subclass;
00556 p._type = arg_type;
00557 p._direction = arg_direction;
00558 p._varying = arg_varying;
00559 p._cat = arg_cat;
00560
00561 if (p._id._name.size() == 0) return true;
00562 if (p._id._name[0] == '$') return true;
00563
00564
00565
00566 size_t loc = p._id._name.find_last_of('.');
00567
00568 string basename (p._id._name);
00569 string struct_name ("");
00570
00571 if (loc < string::npos) {
00572 basename = p._id._name.substr(loc + 1);
00573 struct_name = p._id._name.substr(0,loc+1);
00574 }
00575
00576
00577 vector_string pieces;
00578 tokenize(basename, pieces, "_");
00579
00580 if (basename.size() >= 2 && basename.substr(0, 2) == "__") {
00581 return true;
00582 }
00583
00584
00585 if (pieces[0] == "vtx") {
00586 if ((!cp_errchk_parameter_in(p)) ||
00587 (!cp_errchk_parameter_varying(p)) ||
00588 (!cp_errchk_parameter_float(p, 1, 4))) {
00589 return false;
00590 }
00591 ShaderVarSpec bind;
00592 bind._id = arg_id;
00593 if (pieces.size() == 2) {
00594 if (pieces[1]=="position") {
00595 bind._name = InternalName::get_vertex();
00596 bind._append_uv = -1;
00597 _var_spec.push_back(bind);
00598 return true;
00599 }
00600 if (pieces[1].substr(0,8)=="texcoord") {
00601 bind._name = InternalName::get_texcoord();
00602 bind._append_uv = atoi(pieces[1].c_str()+8);
00603 _var_spec.push_back(bind);
00604 return true;
00605 }
00606 if (pieces[1].substr(0,7)=="tangent") {
00607 bind._name = InternalName::get_tangent();
00608 bind._append_uv = atoi(pieces[1].c_str()+7);
00609 _var_spec.push_back(bind);
00610 return true;
00611 }
00612 if (pieces[1].substr(0,8)=="binormal") {
00613 bind._name = InternalName::get_binormal();
00614 bind._append_uv = atoi(pieces[1].c_str()+8);
00615 _var_spec.push_back(bind);
00616 return true;
00617 }
00618 }
00619 bind._name = InternalName::get_root();
00620 bind._append_uv = -1;
00621 for (int i=1; i<(int)(pieces.size()-0); i++)
00622 bind._name = bind._name->append(pieces[i]);
00623 _var_spec.push_back(bind);
00624 return true;
00625 }
00626
00627
00628
00629
00630 if (pieces[0] == "mstrans") {
00631 pieces[0] = "trans";
00632 pieces.push_back("to");
00633 pieces.push_back("model");
00634 }
00635 if (pieces[0] == "wstrans") {
00636 pieces[0] = "trans";
00637 pieces.push_back("to");
00638 pieces.push_back("world");
00639 }
00640 if (pieces[0] == "vstrans") {
00641 pieces[0] = "trans";
00642 pieces.push_back("to");
00643 pieces.push_back("view");
00644 }
00645 if (pieces[0] == "cstrans") {
00646 pieces[0] = "trans";
00647 pieces.push_back("to");
00648 pieces.push_back("clip");
00649 }
00650 if (pieces[0] == "mspos") {
00651 pieces[0] = "row3";
00652 pieces.push_back("to");
00653 pieces.push_back("model");
00654 }
00655 if (pieces[0] == "wspos") {
00656 pieces[0] = "row3";
00657 pieces.push_back("to");
00658 pieces.push_back("world");
00659 }
00660 if (pieces[0] == "vspos") {
00661 pieces[0] = "row3";
00662 pieces.push_back("to");
00663 pieces.push_back("view");
00664 }
00665 if (pieces[0] == "cspos") {
00666 pieces[0] = "row3";
00667 pieces.push_back("to");
00668 pieces.push_back("clip");
00669 }
00670
00671
00672
00673 if ((pieces[0] == "mat")||(pieces[0] == "inv")||
00674 (pieces[0] == "tps")||(pieces[0] == "itp")) {
00675 if (!cp_errchk_parameter_words(p, 2)) {
00676 return false;
00677 }
00678 string trans = pieces[0];
00679 string matrix = pieces[1];
00680 pieces.clear();
00681 if (matrix == "modelview") {
00682 tokenize("trans_model_to_apiview", pieces, "_");
00683 } else if (matrix == "projection") {
00684 tokenize("trans_apiview_to_apiclip", pieces, "_");
00685 } else if (matrix == "modelproj") {
00686 tokenize("trans_model_to_apiclip", pieces, "_");
00687 } else {
00688 cp_report_error(p,"unrecognized matrix name");
00689 return false;
00690 }
00691 if (trans=="mat") {
00692 pieces[0] = "trans";
00693 } else if (trans=="inv") {
00694 string t = pieces[1];
00695 pieces[1] = pieces[3];
00696 pieces[3] = t;
00697 } else if (trans=="tps") {
00698 pieces[0] = "tpose";
00699 } else if (trans=="itp") {
00700 string t = pieces[1];
00701 pieces[1] = pieces[3];
00702 pieces[3] = t;
00703 pieces[0] = "tpose";
00704 }
00705 }
00706
00707
00708
00709 if ((pieces[0]=="trans")||
00710 (pieces[0]=="tpose")||
00711 (pieces[0]=="row0")||
00712 (pieces[0]=="row1")||
00713 (pieces[0]=="row2")||
00714 (pieces[0]=="row3")||
00715 (pieces[0]=="col0")||
00716 (pieces[0]=="col1")||
00717 (pieces[0]=="col2")||
00718 (pieces[0]=="col3")) {
00719
00720 if ((!cp_errchk_parameter_in(p)) ||
00721 (!cp_errchk_parameter_uniform(p)))
00722 return false;
00723
00724 ShaderMatSpec bind;
00725 bind._id = arg_id;
00726 bind._func = SMF_compose;
00727
00728 int next = 1;
00729 pieces.push_back("");
00730
00731
00732 if (pieces[0]=="trans") bind._piece = SMP_whole;
00733 else if (pieces[0]=="tpose") bind._piece = SMP_transpose;
00734 else if (pieces[0]=="row0") bind._piece = SMP_row0;
00735 else if (pieces[0]=="row1") bind._piece = SMP_row1;
00736 else if (pieces[0]=="row2") bind._piece = SMP_row2;
00737 else if (pieces[0]=="row3") bind._piece = SMP_row3;
00738 else if (pieces[0]=="col0") bind._piece = SMP_col0;
00739 else if (pieces[0]=="col1") bind._piece = SMP_col1;
00740 else if (pieces[0]=="col2") bind._piece = SMP_col2;
00741 else if (pieces[0]=="col3") bind._piece = SMP_col3;
00742 if ((bind._piece == SMP_whole)||(bind._piece == SMP_transpose)) {
00743 if (!cp_errchk_parameter_float(p, 16, 16)) return false;
00744 } else {
00745 if (!cp_errchk_parameter_float(p, 4, 4)) return false;
00746 }
00747
00748 if (!cp_parse_coord_sys(p, pieces, next, bind, true)) {
00749 return false;
00750 }
00751 if (!cp_parse_delimiter(p, pieces, next)) {
00752 return false;
00753 }
00754 if (!cp_parse_coord_sys(p, pieces, next, bind, false)) {
00755 return false;
00756 }
00757 if (!cp_parse_eol(p, pieces, next)) {
00758 return false;
00759 }
00760 cp_optimize_mat_spec(bind);
00761 _mat_spec.push_back(bind);
00762 return true;
00763 }
00764
00765
00766
00767 if (pieces[0] == "attr") {
00768 if ((!cp_errchk_parameter_words(p,2)) ||
00769 (!cp_errchk_parameter_in(p)) ||
00770 (!cp_errchk_parameter_uniform(p))) {
00771 return false;
00772 }
00773 ShaderMatSpec bind;
00774 if (pieces[1] == "material") {
00775 if (!cp_errchk_parameter_float(p,16,16)) {
00776 return false;
00777 }
00778 bind._id = arg_id;
00779 bind._piece = SMP_transpose;
00780 bind._func = SMF_first;
00781 bind._part[0] = SMO_attr_material;
00782 bind._arg[0] = NULL;
00783 bind._part[1] = SMO_identity;
00784 bind._arg[1] = NULL;
00785 } else if (pieces[1] == "color") {
00786 if (!cp_errchk_parameter_float(p,3,4)) {
00787 return false;
00788 }
00789 bind._id = arg_id;
00790 bind._piece = SMP_row3;
00791 bind._func = SMF_first;
00792 bind._part[0] = SMO_attr_color;
00793 bind._arg[0] = NULL;
00794 bind._part[1] = SMO_identity;
00795 bind._arg[1] = NULL;
00796 } else if (pieces[1] == "colorscale") {
00797 if (!cp_errchk_parameter_float(p,3,4)) {
00798 return false;
00799 }
00800 bind._id = arg_id;
00801 bind._piece = SMP_row3;
00802 bind._func = SMF_first;
00803 bind._part[0] = SMO_attr_colorscale;
00804 bind._arg[0] = NULL;
00805 bind._part[1] = SMO_identity;
00806 bind._arg[1] = NULL;
00807 } else if (pieces[1] == "fog") {
00808 if (!cp_errchk_parameter_float(p,3,4)) {
00809 return false;
00810 }
00811 bind._id = arg_id;
00812 bind._piece = SMP_row3;
00813 bind._func = SMF_first;
00814 bind._part[0] = SMO_attr_fog;
00815 bind._arg[0] = NULL;
00816 bind._part[1] = SMO_identity;
00817 bind._arg[1] = NULL;
00818 } else if (pieces[1] == "fogcolor") {
00819 if (!cp_errchk_parameter_float(p,3,4)) {
00820 return false;
00821 }
00822 bind._id = arg_id;
00823 bind._piece = SMP_row3;
00824 bind._func = SMF_first;
00825 bind._part[0] = SMO_attr_fogcolor;
00826 bind._arg[0] = NULL;
00827 bind._part[1] = SMO_identity;
00828 bind._arg[1] = NULL;
00829 } else {
00830 cp_report_error(p,"Unknown attr parameter.");
00831 return false;
00832 }
00833
00834 cp_optimize_mat_spec(bind);
00835 _mat_spec.push_back(bind);
00836 return true;
00837 }
00838
00839 if (pieces[0] == "color") {
00840 if ((!cp_errchk_parameter_words(p,1)) ||
00841 (!cp_errchk_parameter_in(p)) ||
00842 (!cp_errchk_parameter_uniform(p))) {
00843 return false;
00844 }
00845 ShaderMatSpec bind;
00846
00847 cp_optimize_mat_spec(bind);
00848 _mat_spec.push_back(bind);
00849 return true;
00850 }
00851
00852
00853
00854 if (pieces[0] == "alight") {
00855 if ((!cp_errchk_parameter_words(p,2))||
00856 (!cp_errchk_parameter_in(p)) ||
00857 (!cp_errchk_parameter_uniform(p))||
00858 (!cp_errchk_parameter_float(p,3,4))) {
00859 return false;
00860 }
00861 ShaderMatSpec bind;
00862 bind._id = arg_id;
00863 bind._piece = SMP_row3;
00864 bind._func = SMF_first;
00865 bind._part[0] = SMO_alight_x;
00866 bind._arg[0] = InternalName::make(pieces[1]);
00867 bind._part[1] = SMO_identity;
00868 bind._arg[1] = NULL;
00869
00870 cp_optimize_mat_spec(bind);
00871 _mat_spec.push_back(bind);
00872 return true;
00873 }
00874
00875 if (pieces[0] == "satten") {
00876 if ((!cp_errchk_parameter_words(p,2))||
00877 (!cp_errchk_parameter_in(p)) ||
00878 (!cp_errchk_parameter_uniform(p))||
00879 (!cp_errchk_parameter_float(p,4,4))) {
00880 return false;
00881 }
00882 ShaderMatSpec bind;
00883 bind._id = arg_id;
00884 bind._piece = SMP_row3;
00885 bind._func = SMF_first;
00886 bind._part[0] = SMO_satten_x;
00887 bind._arg[0] = InternalName::make(pieces[1]);
00888 bind._part[1] = SMO_identity;
00889 bind._arg[1] = NULL;
00890
00891 cp_optimize_mat_spec(bind);
00892 _mat_spec.push_back(bind);
00893 return true;
00894 }
00895
00896 if ((pieces[0]=="dlight")||(pieces[0]=="plight")||(pieces[0]=="slight")) {
00897 if ((!cp_errchk_parameter_in(p)) ||
00898 (!cp_errchk_parameter_uniform(p))||
00899 (!cp_errchk_parameter_float(p,16,16))) {
00900 return false;
00901 }
00902 ShaderMatSpec bind;
00903 bind._id = arg_id;
00904 bind._piece = SMP_transpose;
00905 int next = 1;
00906 pieces.push_back("");
00907 if (pieces[next] == "") {
00908 cp_report_error(p, "Light name expected");
00909 return false;
00910 }
00911 if (pieces[0] == "dlight") {
00912 bind._func = SMF_transform_dlight;
00913 bind._part[0] = SMO_dlight_x;
00914 } else if (pieces[0] == "plight") {
00915 bind._func = SMF_transform_plight;
00916 bind._part[0] = SMO_plight_x;
00917 } else if (pieces[0] == "slight") {
00918 bind._func = SMF_transform_slight;
00919 bind._part[0] = SMO_slight_x;
00920 }
00921 bind._arg[0] = InternalName::make(pieces[next]);
00922 next += 1;
00923 if (!cp_parse_delimiter(p, pieces, next)) {
00924 return false;
00925 }
00926 if (!cp_parse_coord_sys(p, pieces, next, bind, false)) {
00927 return false;
00928 }
00929 if (!cp_parse_eol(p, pieces, next)) {
00930 return false;
00931 }
00932 cp_optimize_mat_spec(bind);
00933 _mat_spec.push_back(bind);
00934 return true;
00935 }
00936
00937 if (pieces[0] == "texmat") {
00938 if ((!cp_errchk_parameter_words(p,2))||
00939 (!cp_errchk_parameter_in(p)) ||
00940 (!cp_errchk_parameter_uniform(p))||
00941 (!cp_errchk_parameter_float(p,16,16))) {
00942 return false;
00943 }
00944 ShaderMatSpec bind;
00945 bind._id = arg_id;
00946 bind._piece = SMP_whole;
00947 bind._func = SMF_first;
00948 bind._part[0] = SMO_texmat_x;
00949 bind._arg[0] = InternalName::make(pieces[1]);
00950 bind._part[1] = SMO_identity;
00951 bind._arg[1] = NULL;
00952
00953 cp_optimize_mat_spec(bind);
00954 _mat_spec.push_back(bind);
00955 return true;
00956 }
00957
00958 if (pieces[0] == "plane") {
00959 if ((!cp_errchk_parameter_words(p,2))||
00960 (!cp_errchk_parameter_in(p)) ||
00961 (!cp_errchk_parameter_uniform(p))||
00962 (!cp_errchk_parameter_float(p,4,4))) {
00963 return false;
00964 }
00965 ShaderMatSpec bind;
00966 bind._id = arg_id;
00967 bind._piece = SMP_row3;
00968 bind._func = SMF_first;
00969 bind._part[0] = SMO_plane_x;
00970 bind._arg[0] = InternalName::make(pieces[1]);
00971 bind._part[1] = SMO_identity;
00972 bind._arg[1] = NULL;
00973
00974 cp_optimize_mat_spec(bind);
00975 _mat_spec.push_back(bind);
00976 return true;
00977 }
00978
00979 if (pieces[0] == "clipplane") {
00980 if ((!cp_errchk_parameter_words(p,2))||
00981 (!cp_errchk_parameter_in(p)) ||
00982 (!cp_errchk_parameter_uniform(p))||
00983 (!cp_errchk_parameter_float(p,4,4))) {
00984 return false;
00985 }
00986 ShaderMatSpec bind;
00987 bind._id = arg_id;
00988 bind._piece = SMP_row3;
00989 bind._func = SMF_first;
00990 bind._part[0] = SMO_clipplane_x;
00991 bind._arg[0] = InternalName::make(pieces[1]);
00992 bind._part[1] = SMO_identity;
00993 bind._arg[1] = NULL;
00994
00995 cp_optimize_mat_spec(bind);
00996 _mat_spec.push_back(bind);
00997 return true;
00998 }
00999
01000
01001
01002 if (pieces[0] == "sys") {
01003 if ((!cp_errchk_parameter_words(p,2)) ||
01004 (!cp_errchk_parameter_in(p)) ||
01005 (!cp_errchk_parameter_uniform(p))) {
01006 return false;
01007 }
01008 ShaderMatSpec bind;
01009 bind._id = arg_id;
01010 bind._piece = SMP_row3;
01011 bind._func = SMF_first;
01012 bind._part[1] = SMO_identity;
01013 bind._arg[1] = NULL;
01014 if (pieces[1] == "pixelsize") {
01015 if (!cp_errchk_parameter_float(p, 2, 2)) {
01016 return false;
01017 }
01018 bind._part[0] = SMO_pixel_size;
01019 bind._arg[0] = NULL;
01020 } else if (pieces[1] == "windowsize") {
01021 if (!cp_errchk_parameter_float(p, 2, 2)) {
01022 return false;
01023 }
01024 bind._part[0] = SMO_window_size;
01025 bind._arg[0] = NULL;
01026 } else {
01027 cp_report_error(p,"unknown system parameter");
01028 return false;
01029 }
01030
01031 cp_optimize_mat_spec(bind);
01032 _mat_spec.push_back(bind);
01033 return true;
01034 }
01035
01036
01037
01038 if (pieces[0] == "tex") {
01039 if ((!cp_errchk_parameter_in(p)) ||
01040 (!cp_errchk_parameter_uniform(p)) ||
01041 (!cp_errchk_parameter_sampler(p)))
01042 return false;
01043 if ((pieces.size() != 2)&&(pieces.size() != 3)) {
01044 cp_report_error(p, "Invalid parameter name");
01045 return false;
01046 }
01047 ShaderTexSpec bind;
01048 bind._id = arg_id;
01049 bind._name = 0;
01050 bind._stage = atoi(pieces[1].c_str());
01051 switch (p._type) {
01052 case SAT_sampler1d: bind._desired_type = Texture::TT_1d_texture; break;
01053 case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture; break;
01054 case SAT_sampler3d: bind._desired_type = Texture::TT_3d_texture; break;
01055 case SAT_sampler2dArray: bind._desired_type = Texture::TT_2d_texture_array; break;
01056 case SAT_samplercube: bind._desired_type = Texture::TT_cube_map; break;
01057 default:
01058 cp_report_error(p, "Invalid type for a tex-parameter");
01059 return false;
01060 }
01061 if (pieces.size()==3) {
01062 bind._suffix = InternalName::make(((string)"-") + pieces[2]);
01063 }
01064 _tex_spec.push_back(bind);
01065 return true;
01066 }
01067
01068
01069
01070 if (pieces[0] == "texpad") {
01071 if ((!cp_errchk_parameter_words(p,2)) ||
01072 (!cp_errchk_parameter_in(p)) ||
01073 (!cp_errchk_parameter_uniform(p))||
01074 (!cp_errchk_parameter_float(p,3,4))) {
01075 return false;
01076 }
01077 ShaderMatSpec bind;
01078 bind._id = arg_id;
01079 bind._piece = SMP_row3;
01080 bind._func = SMF_first;
01081 bind._part[0] = SMO_texpad_x;
01082 bind._arg[0] = InternalName::make(pieces[1]);
01083 bind._part[1] = SMO_identity;
01084 bind._arg[1] = NULL;
01085 cp_optimize_mat_spec(bind);
01086 _mat_spec.push_back(bind);
01087 return true;
01088 }
01089
01090 if (pieces[0] == "texpix") {
01091 if ((!cp_errchk_parameter_words(p,2)) ||
01092 (!cp_errchk_parameter_in(p)) ||
01093 (!cp_errchk_parameter_uniform(p))||
01094 (!cp_errchk_parameter_float(p,2,4))) {
01095 return false;
01096 }
01097 ShaderMatSpec bind;
01098 bind._id = arg_id;
01099 bind._piece = SMP_row3;
01100 bind._func = SMF_first;
01101 bind._part[0] = SMO_texpix_x;
01102 bind._arg[0] = InternalName::make(pieces[1]);
01103 bind._part[1] = SMO_identity;
01104 bind._arg[1] = NULL;
01105 cp_optimize_mat_spec(bind);
01106 _mat_spec.push_back(bind);
01107 return true;
01108 }
01109
01110 if (pieces[0] == "l") {
01111
01112 return true;
01113 }
01114
01115 if (pieces[0] == "o") {
01116
01117 return true;
01118 }
01119
01120
01121
01122 if ((!cp_errchk_parameter_in(p)) ||
01123 (!cp_errchk_parameter_uniform(p))) {
01124 return false;
01125 }
01126 bool k_prefix = false;
01127
01128
01129 if (pieces[0] == "k") {
01130 k_prefix = true;
01131 basename = basename.substr(2);
01132 }
01133
01134 PT(InternalName) kinputname = InternalName::make(struct_name + basename);
01135
01136 switch (p._class) {
01137 case SAC_vector:
01138 case SAC_matrix:
01139 case SAC_scalar:
01140 case SAC_array: {
01141 if (!cp_errchk_parameter_ptr(p))
01142 return false;
01143
01144 ShaderPtrSpec bind;
01145 bind._id = arg_id;
01146 bind._arg = kinputname;
01147 bind._info = p;
01148 bind._dep[0] = SSD_general | SSD_shaderinputs;
01149 bind._dep[1] = SSD_general | SSD_NONE;
01150
01151 memcpy(bind._dim,arg_dim,sizeof(int)*3);
01152
01153
01154 if (k_prefix) bind._dim[0] = -1;
01155 _ptr_spec.push_back(bind);
01156 return true;
01157 }
01158
01159 case SAC_sampler: {
01160 switch (p._type) {
01161 case SAT_sampler1d: {
01162 ShaderTexSpec bind;
01163 bind._id = arg_id;
01164 bind._name = kinputname;
01165 bind._desired_type = Texture::TT_1d_texture;
01166 _tex_spec.push_back(bind);
01167 return true;
01168 }
01169 case SAT_sampler2d: {
01170 ShaderTexSpec bind;
01171 bind._id = arg_id;
01172 bind._name = kinputname;
01173 bind._desired_type = Texture::TT_2d_texture;
01174 _tex_spec.push_back(bind);
01175 return true;
01176 }
01177 case SAT_sampler3d: {
01178 ShaderTexSpec bind;
01179 bind._id = arg_id;
01180 bind._name = kinputname;
01181 bind._desired_type = Texture::TT_3d_texture;
01182 _tex_spec.push_back(bind);
01183 return true;
01184 }
01185 case SAT_sampler2dArray: {
01186 ShaderTexSpec bind;
01187 bind._id = arg_id;
01188 bind._name = kinputname;
01189 bind._desired_type = Texture::TT_2d_texture_array;
01190 _tex_spec.push_back(bind);
01191 return true;
01192 }
01193 case SAT_samplercube: {
01194 ShaderTexSpec bind;
01195 bind._id = arg_id;
01196 bind._name = kinputname;
01197 bind._desired_type = Texture::TT_cube_map;
01198 _tex_spec.push_back(bind);
01199 return true;
01200 }
01201 default:
01202 cp_report_error(p, "invalid type for non-prefix parameter");
01203 return false;
01204 }
01205 }
01206 default:
01207 cp_report_error(p, "invalid class for non-prefix parameter");
01208 return false;
01209 }
01210
01211 cp_report_error(p, "unrecognized parameter name");
01212 return false;
01213 }
01214
01215
01216
01217
01218
01219
01220
01221 void Shader::
01222 clear_parameters() {
01223 _mat_spec.clear();
01224 _var_spec.clear();
01225 _tex_spec.clear();
01226 }
01227
01228 #ifdef HAVE_CG
01229
01230
01231
01232
01233
01234 Shader::ShaderArgType Shader::
01235 cg_parameter_type(CGparameter p) {
01236
01237 switch (cgGetParameterClass(p)) {
01238 case CG_PARAMETERCLASS_SCALAR: return SAT_scalar;
01239 case CG_PARAMETERCLASS_VECTOR:
01240 switch (cgGetParameterColumns(p)){
01241 case 1: return SAT_vec1;
01242 case 2: return SAT_vec2;
01243 case 3: return SAT_vec3;
01244 case 4: return SAT_vec4;
01245 default: return SAT_unknown;
01246 }
01247 case CG_PARAMETERCLASS_MATRIX:
01248 switch (cgGetParameterRows(p)){
01249 case 1:
01250 switch (cgGetParameterColumns(p)){
01251 case 1: return SAT_mat1x1;
01252 case 2: return SAT_mat1x2;
01253 case 3: return SAT_mat1x3;
01254 case 4: return SAT_mat1x4;
01255 default: return SAT_unknown;
01256 }
01257 case 2:
01258 switch (cgGetParameterColumns(p)){
01259 case 1: return SAT_mat2x1;
01260 case 2: return SAT_mat2x2;
01261 case 3: return SAT_mat2x3;
01262 case 4: return SAT_mat2x4;
01263 default: return SAT_unknown;
01264 }
01265 case 3:
01266 switch (cgGetParameterColumns(p)){
01267 case 1: return SAT_mat3x1;
01268 case 2: return SAT_mat3x2;
01269 case 3: return SAT_mat3x3;
01270 case 4: return SAT_mat3x4;
01271 default: return SAT_unknown;
01272 }
01273 case 4:
01274 switch (cgGetParameterColumns(p)){
01275 case 1: return SAT_mat4x1;
01276 case 2: return SAT_mat4x2;
01277 case 3: return SAT_mat4x3;
01278 case 4: return SAT_mat4x4;
01279 default: return SAT_unknown;
01280 }
01281 default: return SAT_unknown;
01282 }
01283 case CG_PARAMETERCLASS_SAMPLER:
01284 switch (cgGetParameterType(p)){
01285 case CG_SAMPLER1D: return Shader::SAT_sampler1d;
01286 case CG_SAMPLER2D: return Shader::SAT_sampler2d;
01287 case CG_SAMPLER3D: return Shader::SAT_sampler3d;
01288 case CG_SAMPLER2DARRAY: return Shader::SAT_sampler2dArray;
01289 case CG_SAMPLERCUBE: return Shader::SAT_samplercube;
01290
01291 case 1313: return Shader::SAT_sampler1d;
01292 case 1314: return Shader::SAT_sampler2d;
01293 default: return SAT_unknown;
01294 }
01295 case CG_PARAMETERCLASS_ARRAY: return SAT_unknown;
01296 default: return SAT_unknown;
01297 }
01298 }
01299
01300
01301
01302
01303
01304
01305 Shader::ShaderArgClass Shader::cg_parameter_class(CGparameter p) {
01306 switch (cgGetParameterClass(p)) {
01307 case CG_PARAMETERCLASS_SCALAR: return Shader::SAC_scalar;
01308 case CG_PARAMETERCLASS_VECTOR: return Shader::SAC_vector;
01309 case CG_PARAMETERCLASS_MATRIX: return Shader::SAC_matrix;
01310 case CG_PARAMETERCLASS_SAMPLER: return Shader::SAC_sampler;
01311 case CG_PARAMETERCLASS_ARRAY: return Shader::SAC_array;
01312 default: return Shader::SAC_unknown;
01313 }
01314 }
01315
01316
01317
01318
01319
01320
01321 Shader::ShaderArgDir Shader::
01322 cg_parameter_dir(CGparameter p) {
01323 switch (cgGetParameterDirection(p)) {
01324 case CG_IN: return Shader::SAD_in;
01325 case CG_OUT: return Shader::SAD_out;
01326 case CG_INOUT: return Shader::SAD_inout;
01327 default: return Shader::SAD_unknown;
01328 }
01329 }
01330
01331
01332
01333
01334
01335
01336 void Shader::
01337 cg_release_resources() {
01338 if (_cg_vprogram != 0) {
01339 cgDestroyProgram(_cg_vprogram);
01340 _cg_vprogram = 0;
01341 }
01342 if (_cg_fprogram != 0) {
01343 cgDestroyProgram(_cg_fprogram);
01344 _cg_fprogram = 0;
01345 }
01346 if (_cg_gprogram != 0) {
01347 cgDestroyProgram(_cg_gprogram);
01348 _cg_gprogram = 0;
01349 }
01350 if (_cg_context != 0) {
01351 cgDestroyContext(_cg_context);
01352 _cg_context = 0;
01353 }
01354 }
01355
01356
01357
01358
01359
01360
01361 CGprogram Shader::
01362 cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType type) {
01363 CGprogram prog;
01364 CGerror err;
01365 const char *compiler_args[100];
01366 const string text = get_text(type);
01367 int nargs = 0;
01368
01369 int active, ultimate;
01370
01371 switch (type) {
01372 case ST_vertex:
01373 active = caps._active_vprofile;
01374 ultimate = caps._ultimate_vprofile;
01375 break;
01376
01377 case ST_fragment:
01378 active = caps._active_fprofile;
01379 ultimate = caps._ultimate_fprofile;
01380 break;
01381
01382 case ST_geometry:
01383 active = caps._active_gprofile;
01384 ultimate = caps._ultimate_gprofile;
01385 break;
01386
01387 case ST_none:
01388 default:
01389 active = CG_PROFILE_UNKNOWN;
01390 ultimate = CG_PROFILE_UNKNOWN;
01391 };
01392
01393 cgGetError();
01394
01395 if (type == ST_fragment && caps._bug_list.count(SBUG_ati_draw_buffers)) {
01396 compiler_args[nargs++] = "-po";
01397 compiler_args[nargs++] = "ATI_draw_buffers";
01398 }
01399 compiler_args[nargs] = 0;
01400
01401 if ((active != (int)CG_PROFILE_UNKNOWN) && (active != ultimate)) {
01402 prog = cgCreateProgram(_cg_context, CG_SOURCE, text.c_str(),
01403 (CGprofile)active, entry, (const char **)compiler_args);
01404 err = cgGetError();
01405 if (err == CG_NO_ERROR) {
01406 return prog;
01407 }
01408 if (prog != 0) {
01409 cgDestroyProgram(prog);
01410 }
01411 }
01412
01413 prog = cgCreateProgram(_cg_context, CG_SOURCE, text.c_str(),
01414 (CGprofile)ultimate, entry, (const char **)NULL);
01415 err = cgGetError();
01416 if (err == CG_NO_ERROR) {
01417 return prog;
01418 }
01419 if (err == CG_COMPILER_ERROR) {
01420 string listing = cgGetLastListing(_cg_context);
01421 vector_string errlines;
01422 tokenize(listing, errlines, "\n");
01423 for (int i=0; i<(int)errlines.size(); i++) {
01424 string line = trim(errlines[i]);
01425 if (line != "") {
01426 gobj_cat.error() << get_filename(type) << ": " << errlines[i] << "\n";
01427 }
01428 }
01429 } else {
01430 gobj_cat.error() << get_filename(type) << ": " << cgGetErrorString(err) << "\n";
01431 }
01432 if (prog != 0) {
01433 cgDestroyProgram(prog);
01434 }
01435
01436 return 0;
01437 }
01438
01439
01440
01441
01442
01443
01444
01445
01446 bool Shader::
01447 cg_compile_shader(const ShaderCaps &caps) {
01448
01449
01450
01451 if (caps == _cg_last_caps) {
01452 if (_cg_context == 0) {
01453 return false;
01454 } else {
01455 return true;
01456 }
01457 }
01458
01459 _cg_last_caps = caps;
01460
01461 _cg_context = cgCreateContext();
01462
01463 if (!_text->_separate) {
01464 gobj_cat.debug() << "Compiling Shader: \n" << _text << "\n";
01465 }
01466
01467 if (_cg_context == 0) {
01468 gobj_cat.error() << "could not create a Cg context object.\n";
01469 return false;
01470 }
01471
01472 if (!_text->_separate || !_text->_vertex.empty()) {
01473 _cg_vprogram = cg_compile_entry_point("vshader", caps, ST_vertex);
01474 if (_cg_vprogram == 0) {
01475 cg_release_resources();
01476 return false;
01477 }
01478 }
01479
01480 if (!_text->_separate || !_text->_fragment.empty()) {
01481 _cg_fprogram = cg_compile_entry_point("fshader", caps, ST_fragment);
01482 if (_cg_fprogram == 0) {
01483 cg_release_resources();
01484 return false;
01485 }
01486 }
01487
01488 if ((_text->_separate && !_text->_geometry.empty()) || (!_text->_separate && _text->_shared.find("gshader") != string::npos)) {
01489 _cg_gprogram = cg_compile_entry_point("gshader", caps, ST_geometry);
01490 if (_cg_gprogram == 0) {
01491 cg_release_resources();
01492 return false;
01493 }
01494 }
01495
01496 if (_cg_vprogram == 0 && _cg_fprogram == 0 && _cg_gprogram == 0) {
01497 gobj_cat.error() << "Shader must at least have one program!\n";
01498 cg_release_resources();
01499 return false;
01500 }
01501
01502
01503 if (gobj_cat.is_debug()) {
01504 const char *vertex_program;
01505 const char *pixel_program;
01506 const char *geometry_program;
01507
01508 if (_cg_vprogram != 0) {
01509 vertex_program = cgGetProgramString (_cg_vprogram, CG_COMPILED_PROGRAM);
01510 gobj_cat.debug() << vertex_program << "\n";
01511 }
01512 if (_cg_fprogram != 0) {
01513 pixel_program = cgGetProgramString (_cg_fprogram, CG_COMPILED_PROGRAM);
01514 gobj_cat.debug() << pixel_program << "\n";
01515 }
01516 if (_cg_gprogram != 0) {
01517 geometry_program = cgGetProgramString (_cg_gprogram, CG_COMPILED_PROGRAM);
01518 gobj_cat.debug() << geometry_program << "\n";
01519 }
01520 }
01521
01522 return true;
01523 }
01524
01525
01526
01527
01528
01529
01530 bool Shader::
01531 cg_analyze_entry_point(CGprogram prog, ShaderType type) {
01532 bool success = true;
01533
01534 cg_recurse_parameters(cgGetFirstParameter(prog, CG_PROGRAM),type,success);
01535 return success;
01536 }
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571 bool Shader::
01572 cg_analyze_shader(const ShaderCaps &caps) {
01573
01574 if (!cg_compile_shader(caps)) {
01575 return false;
01576 }
01577
01578 if (_cg_fprogram != 0) {
01579 if (!cg_analyze_entry_point(_cg_fprogram, ST_fragment)) {
01580 cg_release_resources();
01581 clear_parameters();
01582 return false;
01583 }
01584 }
01585
01586 if (_var_spec.size() != 0) {
01587 gobj_cat.error() << "Cannot use vtx parameters in an fshader\n";
01588 cg_release_resources();
01589 clear_parameters();
01590 return false;
01591 }
01592
01593 if (_cg_vprogram != 0) {
01594 if (!cg_analyze_entry_point(_cg_vprogram, ST_vertex)) {
01595 cg_release_resources();
01596 clear_parameters();
01597 return false;
01598 }
01599 }
01600
01601 if (_cg_gprogram != 0) {
01602 if (!cg_analyze_entry_point(_cg_gprogram, ST_geometry)) {
01603 cg_release_resources();
01604 clear_parameters();
01605 return false;
01606 }
01607 }
01608
01609
01610 int seqno = 0;
01611 for (int i=0; i<(int)_mat_spec.size(); i++) {
01612 _mat_spec[i]._id._seqno = seqno++;
01613 }
01614 for (int i=0; i<(int)_tex_spec.size(); i++) {
01615 _tex_spec[i]._id._seqno = seqno++;
01616 }
01617 for (int i=0; i<(int)_var_spec.size(); i++) {
01618 _var_spec[i]._id._seqno = seqno++;
01619 }
01620
01621 for (int i=0; i<(int)_ptr_spec.size(); i++) {
01622 _ptr_spec[i]._id._seqno = seqno++;
01623 _ptr_spec[i]._info._id = _ptr_spec[i]._id;
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699 return true;
01700 }
01701
01702
01703
01704
01705
01706
01707
01708 CGprogram Shader::
01709 cg_program_from_shadertype(ShaderType type) {
01710 CGprogram prog;
01711
01712 switch (type) {
01713 case ST_vertex:
01714 prog = _cg_vprogram;
01715 break;
01716
01717 case ST_fragment:
01718 prog = _cg_fprogram;
01719 break;
01720
01721 case ST_geometry:
01722 prog = _cg_gprogram;
01723 break;
01724
01725 default:
01726 prog = 0;
01727 };
01728
01729 return prog;
01730 }
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740 bool Shader::
01741 cg_compile_for(const ShaderCaps &caps,
01742 CGcontext &ctx,
01743 CGprogram &vprogram,
01744 CGprogram &fprogram,
01745 CGprogram &gprogram,
01746 pvector<CGparameter> &map) {
01747
01748
01749
01750 ctx = 0;
01751 vprogram = 0;
01752 fprogram = 0;
01753 gprogram = 0;
01754
01755 map.clear();
01756
01757
01758
01759
01760 _default_caps = caps;
01761 if (!cg_compile_shader(caps)) {
01762 return false;
01763 }
01764
01765
01766
01767
01768
01769 if (_filename->_separate) {
01770 if (_cg_vprogram != 0 && _cg_vprofile == CG_PROFILE_UNKNOWN && cgGetProgramProfile(_cg_vprogram) != caps._active_vprofile) {
01771 gobj_cat.error() << "Cg vprogram too complex for driver: "
01772 << get_filename(ST_vertex) << ". Try choosing a different profile.\n";
01773 return false;
01774 }
01775 if (_cg_fprogram != 0 && _cg_fprofile == CG_PROFILE_UNKNOWN && cgGetProgramProfile(_cg_fprogram) != caps._active_fprofile) {
01776 gobj_cat.error() << "Cg fprogram too complex for driver: "
01777 << get_filename(ST_fragment) << ". Try choosing a different profile.\n";
01778 return false;
01779 }
01780 if (_cg_gprogram != 0 && _cg_gprofile == CG_PROFILE_UNKNOWN && cgGetProgramProfile(_cg_gprogram) != caps._active_gprofile) {
01781 gobj_cat.error() << "Cg gprogram too complex for driver: "
01782 << get_filename(ST_geometry) << ". Try choosing a different profile.\n";
01783 return false;
01784 }
01785 } else {
01786 if ((_cg_vprogram != 0 && _cg_vprofile == CG_PROFILE_UNKNOWN && cgGetProgramProfile(_cg_vprogram) != caps._active_vprofile) ||
01787 (_cg_fprogram != 0 && _cg_fprofile == CG_PROFILE_UNKNOWN && cgGetProgramProfile(_cg_fprogram) != caps._active_fprofile) ||
01788 (_cg_gprogram != 0 && _cg_gprofile == CG_PROFILE_UNKNOWN && cgGetProgramProfile(_cg_gprogram) != caps._active_gprofile)) {
01789 gobj_cat.error() << "Cg program too complex for driver: "
01790 << get_filename() << ". Try choosing a different profile.\n";
01791 return false;
01792 }
01793 }
01794
01795
01796
01797 int n_mat = (int)_mat_spec.size();
01798 int n_tex = (int)_tex_spec.size();
01799 int n_var = (int)_var_spec.size();
01800 int n_ptr = (int)_ptr_spec.size();
01801
01802 map.resize(n_mat + n_tex + n_var + n_ptr);
01803
01804 for (int i=0; i<n_mat; i++) {
01805 const ShaderArgId &id = _mat_spec[i]._id;
01806
01807 CGprogram prog = cg_program_from_shadertype(id._type);
01808 map[id._seqno] = cgGetNamedParameter(prog, id._name.c_str());
01809 }
01810 for (int i=0; i<n_tex; i++) {
01811 const ShaderArgId &id = _tex_spec[i]._id;
01812 CGprogram prog = cg_program_from_shadertype(id._type);
01813 map[id._seqno] = cgGetNamedParameter(prog, id._name.c_str());
01814 if (cgGetParameterBaseResource(map[id._seqno]) == CG_UNDEFINED) {
01815 map[id._seqno] = 0;
01816 }
01817 }
01818 for (int i=0; i<n_var; i++) {
01819 const ShaderArgId &id = _var_spec[i]._id;
01820
01821 CGprogram prog = cg_program_from_shadertype(id._type);
01822 map[id._seqno] = cgGetNamedParameter(prog, id._name.c_str());
01823 if (cgGetParameterBaseResource(map[id._seqno]) == CG_UNDEFINED) {
01824 map[id._seqno] = 0;
01825 }
01826 }
01827 for (int i=0; i<n_ptr; i++) {
01828 const ShaderArgId &id = _ptr_spec[i]._id;
01829
01830 CGprogram prog = cg_program_from_shadertype(id._type);
01831 map[id._seqno] = cgGetNamedParameter(prog, id._name.c_str());
01832 }
01833
01834
01835 ctx = _cg_context;
01836 vprogram = _cg_vprogram;
01837 fprogram = _cg_fprogram;
01838 gprogram = _cg_gprogram;
01839
01840 _cg_context = 0;
01841 _cg_vprogram = 0;
01842 _cg_fprogram = 0;
01843 _cg_gprogram = 0;
01844
01845 _cg_last_caps.clear();
01846
01847 return true;
01848 }
01849 #endif // HAVE_CG
01850
01851
01852
01853
01854
01855
01856 Shader::
01857 Shader(CPT(ShaderFile) filename, CPT(ShaderFile) text, const ShaderLanguage &lang) :
01858 _error_flag(true),
01859 _text(text),
01860 _filename(filename),
01861 _parse(0),
01862 _loaded(false),
01863 _language(lang)
01864 {
01865 _error_flag = false;
01866
01867 #ifdef HAVE_CG
01868 _cg_context = 0;
01869 _cg_vprogram = 0;
01870 _cg_fprogram = 0;
01871 _cg_gprogram = 0;
01872 _cg_vprofile = CG_PROFILE_UNKNOWN;
01873 _cg_fprofile = CG_PROFILE_UNKNOWN;
01874 _cg_gprofile = CG_PROFILE_UNKNOWN;
01875 if (_default_caps._ultimate_vprofile == 0 || _default_caps._ultimate_vprofile == CG_PROFILE_UNKNOWN) {
01876 _default_caps._active_vprofile = CG_PROFILE_UNKNOWN;
01877 _default_caps._active_fprofile = CG_PROFILE_UNKNOWN;
01878 _default_caps._ultimate_vprofile = cgGetProfile("glslv");
01879 _default_caps._ultimate_fprofile = cgGetProfile("glslf");
01880 _default_caps._ultimate_gprofile = cgGetProfile("glslg");
01881 if (_default_caps._ultimate_gprofile == CG_PROFILE_UNKNOWN) {
01882 _default_caps._ultimate_gprofile = cgGetProfile("gp4gp");
01883 }
01884 }
01885 #endif
01886
01887
01888 if (_language == SL_none) {
01889 string header;
01890 parse_init();
01891 parse_line(header, true, true);
01892 if (header == "//Cg") {
01893 _language = SL_Cg;
01894 } else if (header == "//GLSL") {
01895 _language = SL_GLSL;
01896 }
01897 }
01898
01899 if (_language == SL_Cg) {
01900 #ifdef HAVE_CG
01901 if (!_text->_separate) {
01902 cg_get_profile_from_header(_default_caps);
01903 }
01904
01905 if (!cg_analyze_shader(_default_caps)) {
01906 _error_flag = true;
01907 }
01908 #else
01909 gobj_cat.error()
01910 << "Tried to load Cg shader, but no Cg support is enabled.\n";
01911 #endif
01912 } else if (_language == SL_GLSL) {
01913
01914
01915 if (!_text->_separate) {
01916 gobj_cat.error()
01917 << "GLSL shaders must have separate shader bodies!\n";
01918 _error_flag = true;
01919 }
01920 } else {
01921 gobj_cat.error()
01922 << "Shader is not in a supported shader-language.\n";
01923 _error_flag = true;
01924 }
01925 if (_error_flag) {
01926 gobj_cat.error()
01927 << "Shader encountered an error.\n";
01928 }
01929 }
01930
01931 #ifdef HAVE_CG
01932
01933
01934
01935
01936
01937
01938 void Shader::
01939 cg_get_profile_from_header(ShaderCaps& caps) {
01940
01941
01942
01943 string buf;
01944 parse_init();
01945
01946
01947
01948 int lastParse;
01949
01950 do {
01951 lastParse = _parse;
01952 parse_line(buf, true, true);
01953 int profilePos = buf.find("//Cg profile");
01954 if (profilePos >= 0) {
01955
01956 if ((int)buf.find("gp4vp") >= 0)
01957 caps._active_vprofile = cgGetProfile("gp4vp");
01958
01959 if ((int)buf.find("gp5vp") >= 0)
01960 caps._active_vprofile = cgGetProfile("gp5vp");
01961
01962 if ((int)buf.find("glslv") >= 0)
01963 caps._active_vprofile = cgGetProfile("glslv");
01964
01965 if ((int)buf.find("arbvp1") >= 0)
01966 caps._active_vprofile = cgGetProfile("arbvp1");
01967
01968 if ((int)buf.find("vp40") >= 0)
01969 caps._active_vprofile = cgGetProfile("vp40");
01970
01971 if ((int)buf.find("vp30") >= 0)
01972 caps._active_vprofile = cgGetProfile("vp30");
01973
01974 if ((int)buf.find("vp20") >= 0)
01975 caps._active_vprofile = cgGetProfile("vp20");
01976
01977 if ((int)buf.find("vs_1_1") >= 0)
01978 caps._active_vprofile = cgGetProfile("vs_1_1");
01979
01980 if ((int)buf.find("vs_2_0") >= 0)
01981 caps._active_vprofile = cgGetProfile("vs_2_0");
01982
01983 if ((int)buf.find("vs_2_x") >= 0)
01984 caps._active_vprofile = cgGetProfile("vs_2_x");
01985
01986 if ((int)buf.find("vs_3_0") >= 0)
01987 caps._active_vprofile = cgGetProfile("vs_3_0");
01988
01989 if ((int)buf.find("vs_4_0") >= 0)
01990 caps._active_vprofile = cgGetProfile("vs_4_0");
01991
01992 if ((int)buf.find("vs_5_0") >= 0)
01993 caps._active_vprofile = cgGetProfile("vs_5_0");
01994
01995
01996 if ((int)buf.find("gp4fp") >= 0)
01997 caps._active_fprofile = cgGetProfile("gp4fp");
01998
01999 if ((int)buf.find("gp5fp") >= 0)
02000 caps._active_fprofile = cgGetProfile("gp5fp");
02001
02002 if ((int)buf.find("glslf") >= 0)
02003 caps._active_fprofile = cgGetProfile("glslf");
02004
02005 if ((int)buf.find("arbfp1") >= 0)
02006 caps._active_fprofile = cgGetProfile("arbfp1");
02007
02008 if ((int)buf.find("fp40") >= 0)
02009 caps._active_fprofile = cgGetProfile("fp40");
02010
02011 if ((int)buf.find("fp30") >= 0)
02012 caps._active_fprofile = cgGetProfile("fp30");
02013
02014 if ((int)buf.find("fp20") >= 0)
02015 caps._active_fprofile = cgGetProfile("fp20");
02016
02017 if ((int)buf.find("ps_1_1") >= 0)
02018 caps._active_fprofile = cgGetProfile("ps_1_1");
02019
02020 if ((int)buf.find("ps_1_2") >= 0)
02021 caps._active_fprofile = cgGetProfile("ps_1_2");
02022
02023 if ((int)buf.find("ps_1_3") >= 0)
02024 caps._active_fprofile = cgGetProfile("ps_1_3");
02025
02026 if ((int)buf.find("ps_2_0") >= 0)
02027 caps._active_fprofile = cgGetProfile("ps_2_0");
02028
02029 if ((int)buf.find("ps_2_x") >= 0)
02030 caps._active_fprofile = cgGetProfile("ps_2_x");
02031
02032 if ((int)buf.find("ps_3_0") >= 0)
02033 caps._active_fprofile = cgGetProfile("ps_3_0");
02034
02035 if ((int)buf.find("ps_4_0") >= 0)
02036 caps._active_fprofile = cgGetProfile("ps_4_0");
02037
02038 if ((int)buf.find("ps_5_0") >= 0)
02039 caps._active_fprofile = cgGetProfile("ps_5_0");
02040
02041
02042 if ((int)buf.find("gp4gp") >= 0)
02043 caps._active_gprofile = cgGetProfile("gp4gp");
02044
02045 if ((int)buf.find("gp5gp") >= 0)
02046 caps._active_gprofile = cgGetProfile("gp5gp");
02047
02048 if ((int)buf.find("glslg") >= 0)
02049 caps._active_gprofile = cgGetProfile("glslg");
02050
02051 if ((int)buf.find("gs_4_0") >= 0)
02052 caps._active_gprofile = cgGetProfile("gs_4_0");
02053
02054 if ((int)buf.find("gs_5_0") >= 0)
02055 caps._active_gprofile = cgGetProfile("gs_5_0");
02056 }
02057 } while(_parse > lastParse);
02058
02059 }
02060 #endif
02061
02062
02063
02064
02065
02066
02067 Shader::
02068 ~Shader() {
02069 release_all();
02070 if (_loaded) {
02071 _load_table.erase(_filename);
02072 } else {
02073 _make_table.erase(_text);
02074 }
02075 }
02076
02077
02078
02079
02080
02081
02082 PT(Shader) Shader::
02083 load(const Filename &file, const ShaderLanguage &lang) {
02084 PT(ShaderFile) sfile = new ShaderFile(file);
02085 ShaderTable::const_iterator i = _load_table.find(sfile);
02086 if (i != _load_table.end() && (lang == SL_none || lang == i->second->_language)) {
02087 return i->second;
02088 }
02089 PT(ShaderFile) sbody = new ShaderFile("");
02090
02091 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
02092 if (!vfs->read_file(file, sbody->_shared, true)) {
02093 gobj_cat.error() << "Could not read shader file: " << file << "\n";
02094 return NULL;
02095 }
02096 PT(Shader) result = new Shader(sfile, sbody, lang);
02097 result->_loaded = true;
02098 _load_table[sfile] = result;
02099 return result;
02100 }
02101
02102
02103
02104
02105
02106
02107
02108 PT(Shader) Shader::
02109 load(const ShaderLanguage &lang, const Filename &vertex, const Filename &fragment, const Filename &geometry) {
02110 PT(ShaderFile) sfile = new ShaderFile(vertex, fragment, geometry);
02111 ShaderTable::const_iterator i = _load_table.find(sfile);
02112 if (i != _load_table.end() && (lang == SL_none || lang == i->second->_language)) {
02113 return i->second;
02114 }
02115 PT(ShaderFile) sbody = new ShaderFile("", "", "");
02116 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
02117 if (!vertex.empty() && !vfs->read_file(vertex, sbody->_vertex, true)) {
02118 gobj_cat.error() << "Could not read vertex shader file: " << vertex << "\n";
02119 return NULL;
02120 }
02121 if (!fragment.empty() && !vfs->read_file(fragment, sbody->_fragment, true)) {
02122 gobj_cat.error() << "Could not read fragment shader file: " << vertex << "\n";
02123 return NULL;
02124 }
02125 if (!geometry.empty() && !vfs->read_file(geometry, sbody->_geometry, true)) {
02126 gobj_cat.error() << "Could not read geometry shader file: " << vertex << "\n";
02127 return NULL;
02128 }
02129 PT(Shader) result = new Shader(sfile, sbody, lang);
02130 result->_loaded = true;
02131 _load_table[sfile] = result;
02132 return result;
02133 }
02134
02135
02136
02137
02138
02139
02140 PT(Shader) Shader::
02141 make(const string &body, const ShaderLanguage &lang) {
02142 PT(ShaderFile) sbody = new ShaderFile(body);
02143 ShaderTable::const_iterator i = _make_table.find(sbody);
02144 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
02145 return i->second;
02146 }
02147 PT(ShaderFile) sfile = new ShaderFile("created-shader");
02148 PT(Shader) result = new Shader(sfile, sbody, lang);
02149 _make_table[sbody] = result;
02150 if (dump_generated_shaders) {
02151 ostringstream fns;
02152 int index = _shaders_generated ++;
02153 fns << "genshader" << index;
02154 string fn = fns.str();
02155 gobj_cat.warning() << "Dumping shader: " << fn << "\n";
02156 pofstream s;
02157 s.open(fn.c_str());
02158 s << body;
02159 s.close();
02160 }
02161 return result;
02162 }
02163
02164
02165
02166
02167
02168
02169 PT(Shader) Shader::
02170 make(const ShaderLanguage &lang, const string &vertex, const string &fragment, const string &geometry) {
02171 PT(ShaderFile) sbody = new ShaderFile(vertex, fragment, geometry);
02172 ShaderTable::const_iterator i = _make_table.find(sbody);
02173 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
02174 return i->second;
02175 }
02176 PT(ShaderFile) sfile = new ShaderFile("created-shader");
02177 PT(Shader) result = new Shader(sfile, sbody, lang);
02178 _make_table[sbody] = result;
02179 return result;
02180 }
02181
02182
02183
02184
02185
02186
02187 void Shader::
02188 parse_init() {
02189 _parse = 0;
02190 }
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200 void Shader::
02201 parse_line(string &result, bool lt, bool rt) {
02202 nassertv(!_text->_separate);
02203 int len = _text->_shared.size();
02204 int head = _parse;
02205 int tail = head;
02206 while ((tail < len) && (_text->_shared[tail] != '\n')) {
02207 tail++;
02208 }
02209 if (tail < len) {
02210 _parse = tail+1;
02211 } else {
02212 _parse = tail;
02213 }
02214 if (lt) {
02215 while ((head < tail)&&(isspace(_text->_shared[head]))) head++;
02216 while ((tail > head)&&(isspace(_text->_shared[tail-1]))) tail--;
02217 }
02218 result = _text->_shared.substr(head, tail-head);
02219 }
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229 void Shader::
02230 parse_upto(string &result, string pattern, bool include) {
02231 nassertv(!_text->_separate);
02232 GlobPattern endpat(pattern);
02233 int start = _parse;
02234 int last = _parse;
02235 while (_parse < (int)(_text->_shared.size())) {
02236 string t;
02237 parse_line(t, true, true);
02238 if (endpat.matches(t)) break;
02239 last = _parse;
02240 }
02241 if (include) {
02242 result = _text->_shared.substr(start, _parse - start);
02243 } else {
02244 result = _text->_shared.substr(start, last - start);
02245 }
02246 }
02247
02248
02249
02250
02251
02252
02253
02254 void Shader::
02255 parse_rest(string &result) {
02256 nassertv(!_text->_separate);
02257 result = _text->_shared.substr(_parse, _text->_shared.size() - _parse);
02258 }
02259
02260
02261
02262
02263
02264
02265
02266 bool Shader::
02267 parse_eof() {
02268 return (int)_text->_shared.size() == _parse;
02269 }
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283 void Shader::
02284 prepare(PreparedGraphicsObjects *prepared_objects) {
02285 prepared_objects->enqueue_shader(this);
02286 }
02287
02288
02289
02290
02291
02292
02293
02294
02295 bool Shader::
02296 is_prepared(PreparedGraphicsObjects *prepared_objects) const {
02297 Contexts::const_iterator ci;
02298 ci = _contexts.find(prepared_objects);
02299 if (ci != _contexts.end()) {
02300 return true;
02301 }
02302 return prepared_objects->is_shader_queued(this);
02303 }
02304
02305
02306
02307
02308
02309
02310
02311
02312 bool Shader::
02313 release(PreparedGraphicsObjects *prepared_objects) {
02314 Contexts::iterator ci;
02315 ci = _contexts.find(prepared_objects);
02316 if (ci != _contexts.end()) {
02317 ShaderContext *sc = (*ci).second;
02318 if (sc != (ShaderContext *)NULL) {
02319 prepared_objects->release_shader(sc);
02320 } else {
02321 _contexts.erase(ci);
02322 }
02323 return true;
02324 }
02325
02326
02327 return prepared_objects->dequeue_shader(this);
02328 }
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346 ShaderContext *Shader::
02347 prepare_now(PreparedGraphicsObjects *prepared_objects,
02348 GraphicsStateGuardianBase *gsg) {
02349 Contexts::const_iterator ci;
02350 ci = _contexts.find(prepared_objects);
02351 if (ci != _contexts.end()) {
02352 return (*ci).second;
02353 }
02354
02355 ShaderContext *tc = prepared_objects->prepare_shader_now(this, gsg);
02356 _contexts[prepared_objects] = tc;
02357
02358 return tc;
02359 }
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370 void Shader::
02371 clear_prepared(PreparedGraphicsObjects *prepared_objects) {
02372 Contexts::iterator ci;
02373 ci = _contexts.find(prepared_objects);
02374 if (ci != _contexts.end()) {
02375 _contexts.erase(ci);
02376 } else {
02377
02378
02379 nassertv(false);
02380 }
02381 }
02382
02383
02384
02385
02386
02387
02388
02389
02390 int Shader::
02391 release_all() {
02392
02393
02394
02395
02396 Contexts temp = _contexts;
02397 int num_freed = (int)_contexts.size();
02398
02399 Contexts::const_iterator ci;
02400 for (ci = temp.begin(); ci != temp.end(); ++ci) {
02401 PreparedGraphicsObjects *prepared_objects = (*ci).first;
02402 ShaderContext *sc = (*ci).second;
02403 if (sc != (ShaderContext *)NULL) {
02404 prepared_objects->release_shader(sc);
02405 }
02406 }
02407
02408
02409
02410 _contexts.clear();
02411
02412 return num_freed;
02413 }
02414
02415
02416
02417
02418
02419
02420 void Shader::ShaderCaps::
02421 clear() {
02422 _supports_glsl = false;
02423
02424 #ifdef HAVE_CG
02425 _active_vprofile = CG_PROFILE_UNKNOWN;
02426 _active_fprofile = CG_PROFILE_UNKNOWN;
02427 _active_gprofile = CG_PROFILE_UNKNOWN;
02428 _ultimate_vprofile = CG_PROFILE_UNKNOWN;
02429 _ultimate_fprofile = CG_PROFILE_UNKNOWN;
02430 _ultimate_gprofile = CG_PROFILE_UNKNOWN;
02431 #endif
02432 }
02433
02434
02435
02436
02437
02438
02439 void Shader::
02440 register_with_read_factory() {
02441
02442 }
02443