200 *_len -= sizeof (retval); |
214 *_len -= sizeof (retval); |
201 } // else |
215 } // else |
202 return retval; |
216 return retval; |
203 } // readui32 |
217 } // readui32 |
204 |
218 |
205 // !!! FIXME: this is sort of a big, ugly function. |
219 static char *readstring(const uint8 *base, |
206 const MOJOSHADER_effect *MOJOSHADER_parseEffect(const char *profile, |
220 const uint32 offset, |
207 const unsigned char *buf, |
221 MOJOSHADER_malloc m, |
208 const unsigned int _len, |
222 void *d) |
209 const MOJOSHADER_swizzle *swiz, |
223 { |
210 const unsigned int swizcount, |
224 // !!! FIXME: sanity checks! |
211 const MOJOSHADER_samplerMap *smap, |
225 // !!! FIXME: verify this doesn't go past EOF looking for a null. |
212 const unsigned int smapcount, |
226 const char *str = ((const char *) base) + offset; |
213 MOJOSHADER_malloc m, |
227 const uint32 len = *((const uint32 *) str); |
214 MOJOSHADER_free f, |
228 char *strptr = NULL; |
215 void *d) |
229 if (len == 0) return NULL; /* No length? No string. */ |
216 { |
230 strptr = (char *) m(len, d); |
|
231 memcpy(strptr, str + 4, len); |
|
232 return strptr; |
|
233 } // readstring |
|
234 |
|
235 static int findparameter(const MOJOSHADER_effectParam *params, |
|
236 const uint32 param_count, |
|
237 const char *name) |
|
238 { |
|
239 int i; |
|
240 for (i = 0; i < param_count; i++) |
|
241 if (strcmp(name, params[i].value.name) == 0) |
|
242 return i; |
|
243 assert(0 && "Parameter not found!"); |
|
244 } |
|
245 |
|
246 static void readvalue(const uint8 *base, |
|
247 const uint32 typeoffset, |
|
248 const uint32 valoffset, |
|
249 MOJOSHADER_effectValue *value, |
|
250 MOJOSHADER_effectObject *objects, |
|
251 MOJOSHADER_malloc m, |
|
252 void *d) |
|
253 { |
|
254 int i; |
|
255 const uint8 *typeptr = base + typeoffset; |
|
256 const uint8 *valptr = base + valoffset; |
|
257 unsigned int typelen = 9999999; // !!! FIXME |
|
258 const uint32 type = readui32(&typeptr, &typelen); |
|
259 const uint32 valclass = readui32(&typeptr, &typelen); |
|
260 const uint32 name = readui32(&typeptr, &typelen); |
|
261 const uint32 semantic = readui32(&typeptr, &typelen); |
|
262 const uint32 numelements = readui32(&typeptr, &typelen); |
|
263 |
|
264 value->value_type = (MOJOSHADER_symbolType) type; |
|
265 value->value_class = (MOJOSHADER_symbolClass) valclass; |
|
266 value->name = readstring(base, name, m, d); |
|
267 value->semantic = readstring(base, semantic, m, d); |
|
268 value->element_count = numelements; |
|
269 |
|
270 /* Class sanity check */ |
|
271 assert(valclass >= MOJOSHADER_SYMCLASS_SCALAR && valclass <= MOJOSHADER_SYMCLASS_STRUCT); |
|
272 |
|
273 if (valclass == MOJOSHADER_SYMCLASS_SCALAR |
|
274 || valclass == MOJOSHADER_SYMCLASS_VECTOR |
|
275 || valclass == MOJOSHADER_SYMCLASS_MATRIX_ROWS |
|
276 || valclass == MOJOSHADER_SYMCLASS_MATRIX_COLUMNS) |
|
277 { |
|
278 /* These classes only ever contain scalar values */ |
|
279 assert(type >= MOJOSHADER_SYMTYPE_BOOL && type <= MOJOSHADER_SYMTYPE_FLOAT); |
|
280 |
|
281 const uint32 columncount = readui32(&typeptr, &typelen); |
|
282 const uint32 rowcount = readui32(&typeptr, &typelen); |
|
283 |
|
284 value->column_count = columncount; |
|
285 value->row_count = rowcount; |
|
286 |
|
287 uint32 siz = columncount * rowcount; |
|
288 if (numelements > 0) |
|
289 siz *= numelements; |
|
290 value->value_count = siz; |
|
291 siz *= 4; |
|
292 value->values = m(siz, d); |
|
293 memcpy(value->values, valptr, siz); |
|
294 } // if |
|
295 else if (valclass == MOJOSHADER_SYMCLASS_OBJECT) |
|
296 { |
|
297 /* This class contains either samplers or "objects" */ |
|
298 assert(type >= MOJOSHADER_SYMTYPE_STRING && type <= MOJOSHADER_SYMTYPE_VERTEXSHADER); |
|
299 |
|
300 if (type == MOJOSHADER_SYMTYPE_SAMPLER |
|
301 || type == MOJOSHADER_SYMTYPE_SAMPLER1D |
|
302 || type == MOJOSHADER_SYMTYPE_SAMPLER2D |
|
303 || type == MOJOSHADER_SYMTYPE_SAMPLER3D |
|
304 || type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) |
|
305 { |
|
306 unsigned int vallen = 9999999; // !!! FIXME |
|
307 const uint32 numstates = readui32(&valptr, &vallen); |
|
308 |
|
309 value->value_count = numstates; |
|
310 |
|
311 const uint32 siz = sizeof(MOJOSHADER_effectSamplerState) * numstates; |
|
312 value->values = m(siz, d); |
|
313 memset(value->values, '\0', siz); |
|
314 |
|
315 for (i = 0; i < numstates; i++) |
|
316 { |
|
317 MOJOSHADER_effectSamplerState *state = &value->valuesSS[i]; |
|
318 const uint32 stype = readui32(&valptr, &vallen) & ~0xA0; |
|
319 /*const uint32 FIXME =*/ readui32(&valptr, &vallen); |
|
320 const uint32 statetypeoffset = readui32(&valptr, &vallen); |
|
321 const uint32 statevaloffset = readui32(&valptr, &vallen); |
|
322 |
|
323 state->type = (MOJOSHADER_samplerStateType) stype; |
|
324 readvalue(base, statetypeoffset, statevaloffset, |
|
325 &state->value, objects, |
|
326 m, d); |
|
327 if (stype == MOJOSHADER_SAMP_TEXTURE) |
|
328 objects[state->value.valuesI[0]].type = (MOJOSHADER_symbolType) type; |
|
329 } // for |
|
330 } // if |
|
331 else |
|
332 { |
|
333 uint32 numobjects = 1; |
|
334 if (numelements > 0) |
|
335 numobjects = numelements; |
|
336 |
|
337 value->value_count = numobjects; |
|
338 |
|
339 const uint32 siz = 4 * numobjects; |
|
340 value->values = m(siz, d); |
|
341 memcpy(value->values, valptr, siz); |
|
342 |
|
343 for (i = 0; i < value->value_count; i++) |
|
344 objects[value->valuesI[i]].type = (MOJOSHADER_symbolType) type; |
|
345 } // else |
|
346 } // else if |
|
347 else if (valclass == MOJOSHADER_SYMCLASS_STRUCT) |
|
348 { |
|
349 /* TODO: Maybe this is like parse_ctab_typeinfo? -flibit */ |
|
350 assert(0 && "Effect struct value parsing not implemented!"); |
|
351 } // else if |
|
352 } // readvalue |
|
353 |
|
354 static void readannotations(const uint32 numannos, |
|
355 const uint8 *base, |
|
356 const uint8 **ptr, |
|
357 uint32 *len, |
|
358 MOJOSHADER_effectAnnotation **annotations, |
|
359 MOJOSHADER_effectObject *objects, |
|
360 MOJOSHADER_malloc m, |
|
361 void *d) |
|
362 { |
|
363 int i; |
|
364 if (numannos == 0) return; |
|
365 |
|
366 const uint32 siz = sizeof(MOJOSHADER_effectAnnotation) * numannos; |
|
367 *annotations = (MOJOSHADER_effectAnnotation *) m(siz, d); |
|
368 memset(*annotations, '\0', siz); |
|
369 |
|
370 for (i = 0; i < numannos; i++) |
|
371 { |
|
372 MOJOSHADER_effectAnnotation *anno = &(*annotations)[i]; |
|
373 |
|
374 const uint32 typeoffset = readui32(ptr, len); |
|
375 const uint32 valoffset = readui32(ptr, len); |
|
376 |
|
377 readvalue(base, typeoffset, valoffset, |
|
378 anno, objects, |
|
379 m, d); |
|
380 } // for |
|
381 } // readannotation |
|
382 |
|
383 static void readparameters(const uint32 numparams, |
|
384 const uint8 *base, |
|
385 const uint8 **ptr, |
|
386 uint32 *len, |
|
387 MOJOSHADER_effectParam **params, |
|
388 MOJOSHADER_effectObject *objects, |
|
389 MOJOSHADER_malloc m, |
|
390 void *d) |
|
391 { |
|
392 int i; |
|
393 if (numparams == 0) return; |
|
394 |
|
395 uint32 siz = sizeof(MOJOSHADER_effectParam) * numparams; |
|
396 *params = (MOJOSHADER_effectParam *) m(siz, d); |
|
397 memset(*params, '\0', siz); |
|
398 |
|
399 for (i = 0; i < numparams; i++) |
|
400 { |
|
401 MOJOSHADER_effectParam *param = &(*params)[i]; |
|
402 |
|
403 const uint32 typeoffset = readui32(ptr, len); |
|
404 const uint32 valoffset = readui32(ptr, len); |
|
405 /*const uint32 flags =*/ readui32(ptr, len); |
|
406 const uint32 numannos = readui32(ptr, len); |
|
407 |
|
408 param->annotation_count = numannos; |
|
409 readannotations(numannos, base, ptr, len, |
|
410 ¶m->annotations, objects, |
|
411 m, d); |
|
412 |
|
413 readvalue(base, typeoffset, valoffset, |
|
414 ¶m->value, objects, |
|
415 m, d); |
|
416 } // for |
|
417 } // readparameters |
|
418 |
|
419 static void readstates(const uint32 numstates, |
|
420 const uint8 *base, |
|
421 const uint8 **ptr, |
|
422 uint32 *len, |
|
423 MOJOSHADER_effectState **states, |
|
424 MOJOSHADER_effectObject *objects, |
|
425 MOJOSHADER_malloc m, |
|
426 void *d) |
|
427 { |
|
428 int i; |
|
429 if (numstates == 0) return; |
|
430 |
|
431 const uint32 siz = sizeof (MOJOSHADER_effectState) * numstates; |
|
432 *states = (MOJOSHADER_effectState *) m(siz, d); |
|
433 memset(*states, '\0', siz); |
|
434 |
|
435 for (i = 0; i < numstates; i++) |
|
436 { |
|
437 MOJOSHADER_effectState *state = &(*states)[i]; |
|
438 |
|
439 const uint32 type = readui32(ptr, len); |
|
440 /*const uint32 FIXME =*/ readui32(ptr, len); |
|
441 const uint32 typeoffset = readui32(ptr, len); |
|
442 const uint32 valoffset = readui32(ptr, len); |
|
443 |
|
444 state->type = (MOJOSHADER_renderStateType) type; |
|
445 readvalue(base, typeoffset, valoffset, |
|
446 &state->value, objects, |
|
447 m, d); |
|
448 } // for |
|
449 } // readstates |
|
450 |
|
451 static void readpasses(const uint32 numpasses, |
|
452 const uint8 *base, |
|
453 const uint8 **ptr, |
|
454 uint32 *len, |
|
455 MOJOSHADER_effectPass **passes, |
|
456 MOJOSHADER_effectObject *objects, |
|
457 MOJOSHADER_malloc m, |
|
458 void *d) |
|
459 { |
|
460 int i; |
|
461 if (numpasses == 0) return; |
|
462 |
|
463 const uint32 siz = sizeof (MOJOSHADER_effectPass) * numpasses; |
|
464 *passes = (MOJOSHADER_effectPass *) m(siz, d); |
|
465 memset(*passes, '\0', siz); |
|
466 |
|
467 for (i = 0; i < numpasses; i++) |
|
468 { |
|
469 MOJOSHADER_effectPass *pass = &(*passes)[i]; |
|
470 |
|
471 const uint32 passnameoffset = readui32(ptr, len); |
|
472 const uint32 numannos = readui32(ptr, len); |
|
473 const uint32 numstates = readui32(ptr, len); |
|
474 |
|
475 pass->name = readstring(base, passnameoffset, m, d); |
|
476 |
|
477 pass->annotation_count = numannos; |
|
478 readannotations(numannos, base, ptr, len, |
|
479 &pass->annotations, objects, |
|
480 m, d); |
|
481 |
|
482 pass->state_count = numstates; |
|
483 readstates(numstates, base, ptr, len, |
|
484 &pass->states, objects, |
|
485 m, d); |
|
486 } // for |
|
487 } // readpasses |
|
488 |
|
489 static void readtechniques(const uint32 numtechniques, |
|
490 const uint8 *base, |
|
491 const uint8 **ptr, |
|
492 uint32 *len, |
|
493 MOJOSHADER_effectTechnique **techniques, |
|
494 MOJOSHADER_effectObject *objects, |
|
495 MOJOSHADER_malloc m, |
|
496 void *d) |
|
497 { |
|
498 int i; |
|
499 if (numtechniques == 0) return; |
|
500 |
|
501 const uint32 siz = sizeof (MOJOSHADER_effectTechnique) * numtechniques; |
|
502 *techniques = (MOJOSHADER_effectTechnique *) m(siz, d); |
|
503 memset(*techniques, '\0', siz); |
|
504 |
|
505 for (i = 0; i < numtechniques; i++) |
|
506 { |
|
507 MOJOSHADER_effectTechnique *technique = &(*techniques)[i]; |
|
508 |
|
509 const uint32 nameoffset = readui32(ptr, len); |
|
510 const uint32 numannos = readui32(ptr, len); |
|
511 const uint32 numpasses = readui32(ptr, len); |
|
512 |
|
513 technique->name = readstring(base, nameoffset, m, d); |
|
514 |
|
515 technique->annotation_count = numannos; |
|
516 readannotations(numannos, base, ptr, len, |
|
517 &technique->annotations, objects, |
|
518 m, d); |
|
519 |
|
520 technique->pass_count = numpasses; |
|
521 readpasses(numpasses, base, ptr, len, |
|
522 &technique->passes, objects, |
|
523 m, d); |
|
524 } // for |
|
525 } // readtechniques |
|
526 |
|
527 static void readsmallobjects(const uint32 numsmallobjects, |
|
528 const uint8 **ptr, |
|
529 uint32 *len, |
|
530 MOJOSHADER_effect *effect, |
|
531 const char *profile, |
|
532 const MOJOSHADER_swizzle *swiz, |
|
533 const unsigned int swizcount, |
|
534 const MOJOSHADER_samplerMap *smap, |
|
535 const unsigned int smapcount, |
|
536 MOJOSHADER_malloc m, |
|
537 MOJOSHADER_free f, |
|
538 void *d) |
|
539 { |
|
540 int i, j; |
|
541 if (numsmallobjects == 0) return; |
|
542 |
|
543 for (i = 1; i < numsmallobjects + 1; i++) |
|
544 { |
|
545 const uint32 index = readui32(ptr, len); |
|
546 const uint32 length = readui32(ptr, len); |
|
547 |
|
548 MOJOSHADER_effectObject *object = &effect->objects[index]; |
|
549 if (object->type == MOJOSHADER_SYMTYPE_STRING) |
|
550 { |
|
551 if (length > 0) |
|
552 { |
|
553 char *str = (char *) m(length, d); |
|
554 memcpy(str, *ptr, length); |
|
555 object->string.string = str; |
|
556 } // if |
|
557 } // if |
|
558 else if (object->type == MOJOSHADER_SYMTYPE_TEXTURE |
|
559 || object->type == MOJOSHADER_SYMTYPE_TEXTURE1D |
|
560 || object->type == MOJOSHADER_SYMTYPE_TEXTURE2D |
|
561 || object->type == MOJOSHADER_SYMTYPE_TEXTURE3D |
|
562 || object->type == MOJOSHADER_SYMTYPE_TEXTURECUBE) |
|
563 { |
|
564 // No-op. Why is this even here? |
|
565 } // else if |
|
566 else if (object->type == MOJOSHADER_SYMTYPE_SAMPLER |
|
567 || object->type == MOJOSHADER_SYMTYPE_SAMPLER1D |
|
568 || object->type == MOJOSHADER_SYMTYPE_SAMPLER2D |
|
569 || object->type == MOJOSHADER_SYMTYPE_SAMPLER3D |
|
570 || object->type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) |
|
571 { |
|
572 if (length > 0) |
|
573 { |
|
574 char *str = (char *) m(length, d); |
|
575 memcpy(str, *ptr, length); |
|
576 object->mapping.name = str; |
|
577 } // if |
|
578 } // else if |
|
579 else if (object->type == MOJOSHADER_SYMTYPE_PIXELSHADER |
|
580 || object->type == MOJOSHADER_SYMTYPE_VERTEXSHADER) |
|
581 { |
|
582 object->shader.technique = -1; |
|
583 object->shader.pass = -1; |
|
584 object->shader.shader = MOJOSHADER_parse(profile, *ptr, length, |
|
585 swiz, swizcount, smap, smapcount, |
|
586 m, f, d); |
|
587 // !!! FIXME: check for errors. |
|
588 for (j = 0; j < object->shader.shader->symbol_count; j++) |
|
589 if (object->shader.shader->symbols[j].register_set == MOJOSHADER_SYMREGSET_SAMPLER) |
|
590 object->shader.sampler_count++; |
|
591 object->shader.param_count = object->shader.shader->symbol_count; |
|
592 object->shader.params = (uint32 *) m(object->shader.param_count * sizeof (uint32), d); |
|
593 object->shader.samplers = (MOJOSHADER_samplerStateRegister *) m(object->shader.sampler_count * sizeof (MOJOSHADER_samplerStateRegister), d); |
|
594 uint32 curSampler = 0; |
|
595 for (j = 0; j < object->shader.shader->symbol_count; j++) |
|
596 { |
|
597 int par = findparameter(effect->params, |
|
598 effect->param_count, |
|
599 object->shader.shader->symbols[j].name); |
|
600 object->shader.params[j] = par; |
|
601 if (object->shader.shader->symbols[j].register_set == MOJOSHADER_SYMREGSET_SAMPLER) |
|
602 { |
|
603 object->shader.samplers[curSampler].sampler_name = object->shader.shader->symbols[j].name; |
|
604 object->shader.samplers[curSampler].sampler_register = object->shader.shader->symbols[j].register_index; |
|
605 object->shader.samplers[curSampler].sampler_state_count = effect->params[par].value.value_count; |
|
606 object->shader.samplers[curSampler].sampler_states = effect->params[par].value.valuesSS; |
|
607 curSampler++; |
|
608 } // if |
|
609 } // for |
|
610 if (object->shader.shader->preshader) |
|
611 { |
|
612 object->shader.preshader_param_count = object->shader.shader->preshader->symbol_count; |
|
613 object->shader.preshader_params = (uint32 *) m(object->shader.preshader_param_count * sizeof (uint32), d); |
|
614 for (j = 0; j < object->shader.shader->preshader->symbol_count; j++) |
|
615 { |
|
616 object->shader.preshader_params[j] = findparameter(effect->params, |
|
617 effect->param_count, |
|
618 object->shader.shader->preshader->symbols[j].name); |
|
619 } // for |
|
620 } // if |
|
621 } // else if |
|
622 else |
|
623 { |
|
624 assert(0 && "Small object type unknown!"); |
|
625 } // else |
|
626 |
|
627 /* Object block is always a multiple of four */ |
|
628 const uint32 blocklen = (length + 3) - ((length - 1) % 4); |
|
629 *ptr += blocklen; |
|
630 *len -= blocklen; |
|
631 } // for |
|
632 } // readstrings |
|
633 |
|
634 static void readlargeobjects(const uint32 numlargeobjects, |
|
635 const uint32 numsmallobjects, |
|
636 const uint8 **ptr, |
|
637 uint32 *len, |
|
638 MOJOSHADER_effect *effect, |
|
639 const char *profile, |
|
640 const MOJOSHADER_swizzle *swiz, |
|
641 const unsigned int swizcount, |
|
642 const MOJOSHADER_samplerMap *smap, |
|
643 const unsigned int smapcount, |
|
644 MOJOSHADER_malloc m, |
|
645 MOJOSHADER_free f, |
|
646 void *d) |
|
647 { |
|
648 int i, j; |
|
649 if (numlargeobjects == 0) return; |
|
650 |
|
651 int numobjects = numsmallobjects + numlargeobjects + 1; |
|
652 for (i = numsmallobjects + 1; i < numobjects; i++) |
|
653 { |
|
654 const uint32 technique = readui32(ptr, len); |
|
655 const uint32 index = readui32(ptr, len); |
|
656 /*const uint32 FIXME =*/ readui32(ptr, len); |
|
657 const uint32 state = readui32(ptr, len); |
|
658 const uint32 type = readui32(ptr, len); |
|
659 const uint32 length = readui32(ptr, len); |
|
660 |
|
661 uint32 objectIndex; |
|
662 if (technique == -1) |
|
663 objectIndex = effect->params[index].value.valuesSS[state].value.valuesI[0]; |
|
664 else |
|
665 objectIndex = effect->techniques[technique].passes[index].states[state].value.valuesI[0]; |
|
666 |
|
667 MOJOSHADER_effectObject *object = &effect->objects[objectIndex]; |
|
668 if (object->type == MOJOSHADER_SYMTYPE_PIXELSHADER |
|
669 || object->type == MOJOSHADER_SYMTYPE_VERTEXSHADER) |
|
670 { |
|
671 object->shader.technique = technique; |
|
672 object->shader.pass = index; |
|
673 |
|
674 const char *emitter = profile; |
|
675 if (type == 2) |
|
676 { |
|
677 /* This is a standalone preshader! |
|
678 * It exists solely for effect passes that do not use a single |
|
679 * vertex/fragment shader. |
|
680 */ |
|
681 object->shader.is_preshader = 1; |
|
682 const uint32 start = *((uint32 *) *ptr) + 4; |
|
683 const uint32 end = 24; // FIXME: Why? -flibit |
|
684 const char *array = readstring(*ptr, 0, m, d); |
|
685 object->shader.param_count = 1; |
|
686 object->shader.params = (uint32 *) m(sizeof (uint32), d); |
|
687 object->shader.params[0] = findparameter(effect->params, |
|
688 effect->param_count, |
|
689 array); |
|
690 f((void *) array, d); |
|
691 object->shader.preshader = MOJOSHADER_parsePreshader(*ptr + start, length - end, |
|
692 m, f, d); |
|
693 // !!! FIXME: check for errors. |
|
694 object->shader.preshader_param_count = object->shader.preshader->symbol_count; |
|
695 object->shader.preshader_params = (uint32 *) m(object->shader.preshader_param_count * sizeof (uint32), d); |
|
696 for (j = 0; j < object->shader.preshader->symbol_count; j++) |
|
697 { |
|
698 object->shader.preshader_params[j] = findparameter(effect->params, |
|
699 effect->param_count, |
|
700 object->shader.preshader->symbols[j].name); |
|
701 } // for |
|
702 } // if |
|
703 else |
|
704 { |
|
705 object->shader.shader = MOJOSHADER_parse(emitter, *ptr, length, |
|
706 swiz, swizcount, smap, smapcount, |
|
707 m, f, d); |
|
708 // !!! FIXME: check for errors. |
|
709 for (j = 0; j < object->shader.shader->symbol_count; j++) |
|
710 if (object->shader.shader->symbols[j].register_set == MOJOSHADER_SYMREGSET_SAMPLER) |
|
711 object->shader.sampler_count++; |
|
712 object->shader.param_count = object->shader.shader->symbol_count; |
|
713 object->shader.params = (uint32 *) m(object->shader.param_count * sizeof (uint32), d); |
|
714 object->shader.samplers = (MOJOSHADER_samplerStateRegister *) m(object->shader.sampler_count * sizeof (MOJOSHADER_samplerStateRegister), d); |
|
715 uint32 curSampler = 0; |
|
716 for (j = 0; j < object->shader.shader->symbol_count; j++) |
|
717 { |
|
718 int par = findparameter(effect->params, |
|
719 effect->param_count, |
|
720 object->shader.shader->symbols[j].name); |
|
721 object->shader.params[j] = par; |
|
722 if (object->shader.shader->symbols[j].register_set == MOJOSHADER_SYMREGSET_SAMPLER) |
|
723 { |
|
724 object->shader.samplers[curSampler].sampler_name = object->shader.shader->symbols[j].name; |
|
725 object->shader.samplers[curSampler].sampler_register = object->shader.shader->symbols[j].register_index; |
|
726 object->shader.samplers[curSampler].sampler_state_count = effect->params[par].value.value_count; |
|
727 object->shader.samplers[curSampler].sampler_states = effect->params[par].value.valuesSS; |
|
728 curSampler++; |
|
729 } // if |
|
730 } // for |
|
731 if (object->shader.shader->preshader) |
|
732 { |
|
733 object->shader.preshader_param_count = object->shader.shader->preshader->symbol_count; |
|
734 object->shader.preshader_params = (uint32 *) m(object->shader.preshader_param_count * sizeof (uint32), d); |
|
735 for (j = 0; j < object->shader.shader->preshader->symbol_count; j++) |
|
736 { |
|
737 object->shader.preshader_params[j] = findparameter(effect->params, |
|
738 effect->param_count, |
|
739 object->shader.shader->preshader->symbols[j].name); |
|
740 } // for |
|
741 } // if |
|
742 } |
|
743 } // if |
|
744 else if (object->type == MOJOSHADER_SYMTYPE_SAMPLER |
|
745 || object->type == MOJOSHADER_SYMTYPE_SAMPLER1D |
|
746 || object->type == MOJOSHADER_SYMTYPE_SAMPLER2D |
|
747 || object->type == MOJOSHADER_SYMTYPE_SAMPLER3D |
|
748 || object->type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) |
|
749 { |
|
750 if (length > 0) |
|
751 { |
|
752 char *str = (char *) m(length, d); |
|
753 memcpy(str, *ptr, length); |
|
754 object->mapping.name = str; |
|
755 } // if |
|
756 } // else if |
|
757 else if (object->type != MOJOSHADER_SYMTYPE_VOID) // FIXME: Why? -flibit |
|
758 { |
|
759 assert(0 && "Large object type unknown!"); |
|
760 } // else |
|
761 |
|
762 /* Object block is always a multiple of four */ |
|
763 const uint32 blocklen = (length + 3) - ((length - 1) % 4); |
|
764 *ptr += blocklen; |
|
765 *len -= blocklen; |
|
766 } // for |
|
767 } // readobjects |
|
768 |
|
769 MOJOSHADER_effect *MOJOSHADER_parseEffect(const char *profile, |
|
770 const unsigned char *buf, |
|
771 const unsigned int _len, |
|
772 const MOJOSHADER_swizzle *swiz, |
|
773 const unsigned int swizcount, |
|
774 const MOJOSHADER_samplerMap *smap, |
|
775 const unsigned int smapcount, |
|
776 MOJOSHADER_malloc m, |
|
777 MOJOSHADER_free f, |
|
778 void *d) |
|
779 { |
|
780 const uint8 *ptr = (const uint8 *) buf; |
|
781 uint32 len = (uint32) _len; |
|
782 |
|
783 /* Supply both m and f, or neither */ |
217 if ( ((m == NULL) && (f != NULL)) || ((m != NULL) && (f == NULL)) ) |
784 if ( ((m == NULL) && (f != NULL)) || ((m != NULL) && (f == NULL)) ) |
218 return &MOJOSHADER_out_of_mem_effect; // supply both or neither. |
785 return &MOJOSHADER_out_of_mem_effect; |
219 |
786 |
|
787 /* Use default malloc/free if m/f were not passed */ |
220 if (m == NULL) m = MOJOSHADER_internal_malloc; |
788 if (m == NULL) m = MOJOSHADER_internal_malloc; |
221 if (f == NULL) f = MOJOSHADER_internal_free; |
789 if (f == NULL) f = MOJOSHADER_internal_free; |
222 |
790 |
223 MOJOSHADER_effect *retval = m(sizeof (MOJOSHADER_effect), d); |
791 /* malloc base effect structure */ |
|
792 MOJOSHADER_effect *retval = (MOJOSHADER_effect *) m(sizeof (MOJOSHADER_effect), d); |
224 if (retval == NULL) |
793 if (retval == NULL) |
225 return &MOJOSHADER_out_of_mem_effect; // supply both or neither. |
794 return &MOJOSHADER_out_of_mem_effect; |
226 memset(retval, '\0', sizeof (*retval)); |
795 memset(retval, '\0', sizeof (*retval)); |
227 |
796 |
|
797 /* Store m/f/d in effect structure */ |
228 retval->malloc = m; |
798 retval->malloc = m; |
229 retval->free = f; |
799 retval->free = f; |
230 retval->malloc_data = d; |
800 retval->malloc_data = d; |
231 |
801 |
232 const uint8 *ptr = (const uint8 *) buf; |
|
233 uint32 len = (uint32) _len; |
|
234 size_t siz = 0; |
|
235 int i, j, k; |
|
236 |
|
237 if (len < 8) |
802 if (len < 8) |
238 goto parseEffect_unexpectedEOF; |
803 goto parseEffect_unexpectedEOF; |
239 |
804 |
|
805 /* Read in header magic, seek to initial offset */ |
240 const uint8 *base = NULL; |
806 const uint8 *base = NULL; |
241 if (readui32(&ptr, &len) != 0xFEFF0901) // !!! FIXME: is this always magic? |
807 uint32 header = readui32(&ptr, &len); |
|
808 if (header == 0xBCF00BCF) |
|
809 { |
|
810 /* The Effect compiler provided with XNA4 adds some extra mess at the |
|
811 * beginning of the file. It's useless though, so just skip it. |
|
812 * -flibit |
|
813 */ |
|
814 const uint32 skip = readui32(&ptr, &len) - 8; |
|
815 ptr += skip; |
|
816 len += skip; |
|
817 header = readui32(&ptr, &len); |
|
818 } // if |
|
819 if (header != 0xFEFF0901) |
242 goto parseEffect_notAnEffectsFile; |
820 goto parseEffect_notAnEffectsFile; |
243 else |
821 else |
244 { |
822 { |
245 const uint32 offset = readui32(&ptr, &len); |
823 const uint32 offset = readui32(&ptr, &len); |
246 base = ptr; |
824 base = ptr; |
247 //printf("base offset == %u\n", offset); |
|
248 if (offset > len) |
825 if (offset > len) |
249 goto parseEffect_unexpectedEOF; |
826 goto parseEffect_unexpectedEOF; |
250 ptr += offset; |
827 ptr += offset; |
251 len -= offset; |
828 len -= offset; |
252 } // else |
829 } // else |
253 |
830 |
254 // params... |
|
255 |
|
256 if (len < 16) |
831 if (len < 16) |
257 goto parseEffect_unexpectedEOF; |
832 goto parseEffect_unexpectedEOF; |
258 |
833 |
|
834 /* Parse structure counts */ |
259 const uint32 numparams = readui32(&ptr, &len); |
835 const uint32 numparams = readui32(&ptr, &len); |
260 const uint32 numtechniques = readui32(&ptr, &len); |
836 const uint32 numtechniques = readui32(&ptr, &len); |
261 |
837 /*const uint32 FIXME =*/ readui32(&ptr, &len); |
262 readui32(&ptr, &len); // !!! FIXME: there are 8 unknown bytes here. Annotations? |
838 const uint32 numobjects = readui32(&ptr, &len); |
263 /*const uint32 numobjects = */ readui32(&ptr, &len); |
839 |
264 |
840 /* Alloc structures now, so object types can be stored */ |
265 if (numparams > 0) |
841 retval->object_count = numobjects; |
266 { |
842 const uint32 siz = sizeof (MOJOSHADER_effectObject) * numobjects; |
267 siz = sizeof (MOJOSHADER_effectParam) * numparams; |
843 retval->objects = (MOJOSHADER_effectObject *) m(siz, d); |
268 retval->params = (MOJOSHADER_effectParam *) m(siz, d); |
844 if (retval->objects == NULL) |
269 if (retval->params == NULL) |
845 goto parseEffect_outOfMemory; |
270 goto parseEffect_outOfMemory; |
846 memset(retval->objects, '\0', siz); |
271 memset(retval->params, '\0', siz); |
847 |
272 |
848 /* Parse effect parameters */ |
273 retval->param_count = numparams; |
849 retval->param_count = numparams; |
274 |
850 readparameters(numparams, base, &ptr, &len, |
275 for (i = 0; i < numparams; i++) |
851 &retval->params, retval->objects, |
276 { |
852 m, d); |
277 if (len < 16) |
853 |
278 goto parseEffect_unexpectedEOF; |
854 /* Parse effect techniques */ |
279 |
855 retval->technique_count = numtechniques; |
280 const uint32 typeoffset = readui32(&ptr, &len); |
856 readtechniques(numtechniques, base, &ptr, &len, |
281 /*const uint32 valoffset =*/ readui32(&ptr, &len); |
857 &retval->techniques, retval->objects, |
282 /*const uint32 flags =*/ readui32(&ptr, &len); |
858 m, d); |
283 const uint32 numannos = readui32(&ptr, &len); |
859 |
284 for (j = 0; j < numannos; j++) |
860 /* Initial effect technique/pass */ |
285 { |
861 retval->current_technique = &retval->techniques[0]; |
286 if (len < 8) |
862 retval->current_pass = -1; |
287 goto parseEffect_unexpectedEOF; |
|
288 // !!! FIXME: parse annotations. |
|
289 readui32(&ptr, &len); |
|
290 readui32(&ptr, &len); |
|
291 } // for |
|
292 |
|
293 const uint8 *typeptr = base + typeoffset; |
|
294 unsigned int typelen = 9999999; // !!! FIXME |
|
295 /*const uint32 paramtype =*/ readui32(&typeptr, &typelen); |
|
296 /*const uint32 paramclass =*/ readui32(&typeptr, &typelen); |
|
297 const uint32 paramname = readui32(&typeptr, &typelen); |
|
298 const uint32 paramsemantic = readui32(&typeptr, &typelen); |
|
299 |
|
300 // !!! FIXME: sanity checks! |
|
301 const char *namestr = ((const char *) base) + paramname; |
|
302 const char *semstr = ((const char *) base) + paramsemantic; |
|
303 uint32 len; |
|
304 char *strptr; |
|
305 len = *((const uint32 *) namestr); |
|
306 strptr = (char *) m(len + 1, d); |
|
307 memcpy(strptr, namestr + 4, len); |
|
308 strptr[len] = '\0'; |
|
309 retval->params[i].name = strptr; |
|
310 len = *((const uint32 *) semstr); |
|
311 strptr = (char *) m(len + 1, d); |
|
312 memcpy(strptr, semstr + 4, len); |
|
313 strptr[len] = '\0'; |
|
314 retval->params[i].semantic = strptr; |
|
315 } // for |
|
316 } // if |
|
317 |
|
318 uint32 numshaders = 0; // we'll calculate this later. |
|
319 |
|
320 // techniques... |
|
321 |
|
322 if (numtechniques > 0) |
|
323 { |
|
324 siz = sizeof (MOJOSHADER_effectTechnique) * numtechniques; |
|
325 retval->techniques = (MOJOSHADER_effectTechnique *) m(siz, d); |
|
326 if (retval->techniques == NULL) |
|
327 goto parseEffect_outOfMemory; |
|
328 memset(retval->techniques, '\0', siz); |
|
329 |
|
330 retval->technique_count = numtechniques; |
|
331 |
|
332 for (i = 0; i < numtechniques; i++) |
|
333 { |
|
334 if (len < 12) |
|
335 goto parseEffect_unexpectedEOF; |
|
336 |
|
337 MOJOSHADER_effectTechnique *technique = &retval->techniques[i]; |
|
338 |
|
339 const uint32 nameoffset = readui32(&ptr, &len); |
|
340 const uint32 numannos = readui32(&ptr, &len); |
|
341 const uint32 numpasses = readui32(&ptr, &len); |
|
342 |
|
343 if (nameoffset >= _len) |
|
344 goto parseEffect_unexpectedEOF; |
|
345 |
|
346 if (numannos > 0) |
|
347 { |
|
348 // !!! FIXME: expose these to the caller? |
|
349 for (j = 0; j < numannos; j++) |
|
350 { |
|
351 if (len < 8) |
|
352 goto parseEffect_unexpectedEOF; |
|
353 readui32(&ptr, &len); // typedef offset |
|
354 readui32(&ptr, &len); // value offset |
|
355 } // for |
|
356 } // if |
|
357 |
|
358 // !!! FIXME: verify this doesn't go past EOF looking for a null. |
|
359 { |
|
360 const char *namestr = ((char *) base) + nameoffset; |
|
361 uint32 len = *((const uint32 *) namestr); |
|
362 char *strptr = (char *) m(len + 1, d); |
|
363 memcpy(strptr, namestr + 4, len); |
|
364 strptr[len] = '\0'; |
|
365 technique->name = strptr; |
|
366 } |
|
367 |
|
368 if (numpasses > 0) |
|
369 { |
|
370 technique->pass_count = numpasses; |
|
371 |
|
372 siz = sizeof (MOJOSHADER_effectPass) * numpasses; |
|
373 technique->passes = (MOJOSHADER_effectPass *) m(siz, d); |
|
374 if (technique->passes == NULL) |
|
375 goto parseEffect_outOfMemory; |
|
376 memset(technique->passes, '\0', siz); |
|
377 |
|
378 for (j = 0; j < numpasses; j++) |
|
379 { |
|
380 if (len < 12) |
|
381 goto parseEffect_unexpectedEOF; |
|
382 |
|
383 MOJOSHADER_effectPass *pass = &technique->passes[j]; |
|
384 |
|
385 const uint32 passnameoffset = readui32(&ptr, &len); |
|
386 const uint32 numannos = readui32(&ptr, &len); |
|
387 const uint32 numstates = readui32(&ptr, &len); |
|
388 |
|
389 if (passnameoffset >= _len) |
|
390 goto parseEffect_unexpectedEOF; |
|
391 |
|
392 // !!! FIXME: verify this doesn't go past EOF looking for a null. |
|
393 { |
|
394 const char *namestr = ((char *) base) + passnameoffset; |
|
395 uint32 len = *((const uint32 *) namestr); |
|
396 char *strptr = (char *) m(len + 1, d); |
|
397 memcpy(strptr, namestr + 4, len); |
|
398 strptr[len] = '\0'; |
|
399 pass->name = strptr; |
|
400 } |
|
401 |
|
402 if (numannos > 0) |
|
403 { |
|
404 for (k = 0; k < numannos; k++) |
|
405 { |
|
406 if (len < 8) |
|
407 goto parseEffect_unexpectedEOF; |
|
408 // !!! FIXME: do something with this. |
|
409 readui32(&ptr, &len); |
|
410 readui32(&ptr, &len); |
|
411 } // for |
|
412 } // if |
|
413 |
|
414 if (numstates > 0) |
|
415 { |
|
416 pass->state_count = numstates; |
|
417 |
|
418 siz = sizeof (MOJOSHADER_effectState) * numstates; |
|
419 pass->states = (MOJOSHADER_effectState *) m(siz, d); |
|
420 if (pass->states == NULL) |
|
421 goto parseEffect_outOfMemory; |
|
422 memset(pass->states, '\0', siz); |
|
423 |
|
424 for (k = 0; k < numstates; k++) |
|
425 { |
|
426 if (len < 16) |
|
427 goto parseEffect_unexpectedEOF; |
|
428 |
|
429 MOJOSHADER_effectState *state = &pass->states[k]; |
|
430 const uint32 type = readui32(&ptr, &len); |
|
431 readui32(&ptr, &len); // !!! FIXME: don't know what this field does. |
|
432 /*const uint32 offsetend = */ readui32(&ptr, &len); |
|
433 /*const uint32 offsetstart = */ readui32(&ptr, &len); |
|
434 state->type = type; |
|
435 |
|
436 if ((type == 0x92) || (type == 0x93)) |
|
437 numshaders++; |
|
438 } // for |
|
439 } // if |
|
440 } // for |
|
441 } // if |
|
442 } // for |
|
443 } // if |
|
444 |
|
445 // textures... |
|
446 |
863 |
447 if (len < 8) |
864 if (len < 8) |
448 goto parseEffect_unexpectedEOF; |
865 goto parseEffect_unexpectedEOF; |
449 |
866 |
450 const int numtextures = readui32(&ptr, &len); |
867 /* Parse object counts */ |
451 const int numobjects = readui32(&ptr, &len); // !!! FIXME: "objects" for lack of a better word. |
868 const int numsmallobjects = readui32(&ptr, &len); |
452 |
869 const int numlargeobjects = readui32(&ptr, &len); |
453 if (numtextures > 0) |
870 |
454 { |
871 /* Parse "small" object table */ |
455 siz = sizeof (MOJOSHADER_effectTexture) * numtextures; |
872 readsmallobjects(numsmallobjects, &ptr, &len, |
456 retval->textures = m(siz, d); |
873 retval, |
457 if (retval->textures == NULL) |
874 profile, swiz, swizcount, smap, smapcount, |
458 goto parseEffect_outOfMemory; |
875 m, f, d); |
459 memset(retval->textures, '\0', siz); |
876 |
460 |
877 /* Parse "large" object table. */ |
461 for (i = 0; i < numtextures; i++) |
878 readlargeobjects(numlargeobjects, numsmallobjects, &ptr, &len, |
462 { |
879 retval, |
463 if (len < 8) |
880 profile, swiz, swizcount, smap, smapcount, |
464 goto parseEffect_unexpectedEOF; |
881 m, f, d); |
465 |
882 |
466 MOJOSHADER_effectTexture *texture = &retval->textures[i]; |
883 /* Store MojoShader profile in effect structure */ |
467 const uint32 texparam = readui32(&ptr, &len); |
|
468 const uint32 texsize = readui32(&ptr, &len); |
|
469 // apparently texsize will pad out to 32 bits. |
|
470 const uint32 readsize = (((texsize + 3) / 4) * 4); |
|
471 if (len < readsize) |
|
472 goto parseEffect_unexpectedEOF; |
|
473 |
|
474 texture->param = texparam; |
|
475 char *str = m(texsize + 1, d); |
|
476 if (str == NULL) |
|
477 goto parseEffect_outOfMemory; |
|
478 memcpy(str, ptr, texsize); |
|
479 str[texsize] = '\0'; |
|
480 texture->name = str; |
|
481 |
|
482 ptr += readsize; |
|
483 len -= readsize; |
|
484 } // for |
|
485 } // if |
|
486 |
|
487 // shaders... |
|
488 |
|
489 if (numshaders > 0) |
|
490 { |
|
491 siz = sizeof (MOJOSHADER_effectShader) * numshaders; |
|
492 retval->shaders = (MOJOSHADER_effectShader *) m(siz, d); |
|
493 if (retval->shaders == NULL) |
|
494 goto parseEffect_outOfMemory; |
|
495 memset(retval->shaders, '\0', siz); |
|
496 |
|
497 retval->shader_count = numshaders; |
|
498 |
|
499 // !!! FIXME: I wonder if we should pull these from offsets and not |
|
500 // !!! FIXME: count on them all being in a line like this. |
|
501 for (i = 0; i < numshaders; i++) |
|
502 { |
|
503 if (len < 24) |
|
504 goto parseEffect_unexpectedEOF; |
|
505 |
|
506 MOJOSHADER_effectShader *shader = &retval->shaders[i]; |
|
507 const uint32 technique = readui32(&ptr, &len); |
|
508 const uint32 pass = readui32(&ptr, &len); |
|
509 readui32(&ptr, &len); // !!! FIXME: don't know what this does. |
|
510 readui32(&ptr, &len); // !!! FIXME: don't know what this does (vertex/pixel/geometry?) |
|
511 readui32(&ptr, &len); // !!! FIXME: don't know what this does. |
|
512 const uint32 shadersize = readui32(&ptr, &len); |
|
513 |
|
514 if (len < shadersize) |
|
515 goto parseEffect_unexpectedEOF; |
|
516 |
|
517 shader->technique = technique; |
|
518 shader->pass = pass; |
|
519 shader->shader = MOJOSHADER_parse(profile, ptr, shadersize, |
|
520 swiz, swizcount, smap, smapcount, |
|
521 m, f, d); |
|
522 |
|
523 // !!! FIXME: check for errors. |
|
524 |
|
525 ptr += shadersize; |
|
526 len -= shadersize; |
|
527 } // for |
|
528 } // if |
|
529 |
|
530 // !!! FIXME: we parse this, but don't expose the data, yet. |
|
531 // mappings ... |
|
532 assert(numshaders <= numobjects); |
|
533 const uint32 nummappings = numobjects - numshaders; |
|
534 if (nummappings > 0) |
|
535 { |
|
536 for (i = 0; i < nummappings; i++) |
|
537 { |
|
538 if (len < 24) |
|
539 goto parseEffect_unexpectedEOF; |
|
540 |
|
541 /*const uint32 magic = */ readui32(&ptr, &len); |
|
542 /*const uint32 index = */ readui32(&ptr, &len); |
|
543 readui32(&ptr, &len); // !!! FIXME: what is this field? |
|
544 readui32(&ptr, &len); // !!! FIXME: what is this field? |
|
545 /*const uint32 type = */ readui32(&ptr, &len); |
|
546 const uint32 mapsize = readui32(&ptr, &len); |
|
547 if (mapsize > 0) |
|
548 { |
|
549 const uint32 readsize = (((mapsize + 3) / 4) * 4); |
|
550 if (len < readsize) |
|
551 goto parseEffect_unexpectedEOF; |
|
552 } // if |
|
553 } // for |
|
554 } // if |
|
555 |
|
556 retval->profile = (char *) m(strlen(profile) + 1, d); |
884 retval->profile = (char *) m(strlen(profile) + 1, d); |
557 if (retval->profile == NULL) |
885 if (retval->profile == NULL) |
558 goto parseEffect_outOfMemory; |
886 goto parseEffect_outOfMemory; |
559 strcpy((char *) retval->profile, profile); |
887 strcpy((char *) retval->profile, profile); |
560 |
888 |
561 return retval; |
889 return retval; |
562 |
|
563 |
890 |
564 // !!! FIXME: do something with this. |
891 // !!! FIXME: do something with this. |
565 parseEffect_notAnEffectsFile: |
892 parseEffect_notAnEffectsFile: |
566 parseEffect_unexpectedEOF: |
893 parseEffect_unexpectedEOF: |
567 parseEffect_outOfMemory: |
894 parseEffect_outOfMemory: |
568 MOJOSHADER_freeEffect(retval); |
895 MOJOSHADER_freeEffect(retval); |
569 return &MOJOSHADER_out_of_mem_effect; |
896 return &MOJOSHADER_out_of_mem_effect; |
570 } // MOJOSHADER_parseEffect |
897 } // MOJOSHADER_parseEffect |
571 |
898 |
572 |
899 |
|
900 void freevalue(MOJOSHADER_effectValue *value, MOJOSHADER_free f, void *d) |
|
901 { |
|
902 int i; |
|
903 f((void *) value->name, d); |
|
904 f((void *) value->semantic, d); |
|
905 if (value->value_type == MOJOSHADER_SYMTYPE_SAMPLER |
|
906 || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER1D |
|
907 || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER2D |
|
908 || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER3D |
|
909 || value->value_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) |
|
910 for (i = 0; i < value->value_count; i++) |
|
911 freevalue(&value->valuesSS[i].value, f, d); |
|
912 f(value->values, d); |
|
913 } // freevalue |
|
914 |
|
915 |
573 void MOJOSHADER_freeEffect(const MOJOSHADER_effect *_effect) |
916 void MOJOSHADER_freeEffect(const MOJOSHADER_effect *_effect) |
574 { |
917 { |
575 MOJOSHADER_effect *effect = (MOJOSHADER_effect *) _effect; |
918 MOJOSHADER_effect *effect = (MOJOSHADER_effect *) _effect; |
576 if ((effect == NULL) || (effect == &MOJOSHADER_out_of_mem_effect)) |
919 if ((effect == NULL) || (effect == &MOJOSHADER_out_of_mem_effect)) |
577 return; // no-op. |
920 return; // no-op. |
578 |
921 |
579 MOJOSHADER_free f = effect->free; |
922 MOJOSHADER_free f = effect->free; |
580 void *d = effect->malloc_data; |
923 void *d = effect->malloc_data; |
581 int i, j; |
924 int i, j, k; |
582 |
925 |
|
926 /* Free errors */ |
583 for (i = 0; i < effect->error_count; i++) |
927 for (i = 0; i < effect->error_count; i++) |
584 { |
928 { |
585 f((void *) effect->errors[i].error, d); |
929 f((void *) effect->errors[i].error, d); |
586 f((void *) effect->errors[i].filename, d); |
930 f((void *) effect->errors[i].filename, d); |
587 } // for |
931 } // for |
588 f((void *) effect->errors, d); |
932 f((void *) effect->errors, d); |
589 |
933 |
|
934 /* Free profile string */ |
590 f((void *) effect->profile, d); |
935 f((void *) effect->profile, d); |
591 |
936 |
|
937 /* Free parameters, including annotations */ |
592 for (i = 0; i < effect->param_count; i++) |
938 for (i = 0; i < effect->param_count; i++) |
593 { |
939 { |
594 f((void *) effect->params[i].name, d); |
940 MOJOSHADER_effectParam *param = &effect->params[i]; |
595 f((void *) effect->params[i].semantic, d); |
941 freevalue(¶m->value, f, d); |
596 } // for |
942 for (j = 0; j < param->annotation_count; j++) |
597 f(effect->params, d); |
943 { |
598 |
944 freevalue(¶m->annotations[j], f, d); |
|
945 } // for |
|
946 f((void *) param->annotations, d); |
|
947 } // for |
|
948 f((void *) effect->params, d); |
|
949 |
|
950 /* Free techniques, including passes and all annotations */ |
599 for (i = 0; i < effect->technique_count; i++) |
951 for (i = 0; i < effect->technique_count; i++) |
600 { |
952 { |
601 MOJOSHADER_effectTechnique *technique = &effect->techniques[i]; |
953 MOJOSHADER_effectTechnique *technique = &effect->techniques[i]; |
602 f((void *) technique->name, d); |
954 f((void *) technique->name, d); |
603 for (j = 0; j < technique->pass_count; j++) |
955 for (j = 0; j < technique->pass_count; j++) |
604 { |
956 { |
605 f((void *) technique->passes[j].name, d); |
957 MOJOSHADER_effectPass *pass = &technique->passes[j]; |
606 f(technique->passes[j].states, d); |
958 f((void *) pass->name, d); |
|
959 for (k = 0; k < pass->state_count; k++) |
|
960 { |
|
961 freevalue(&pass->states[k].value, f, d); |
|
962 } // for |
|
963 f((void *) pass->states, d); |
|
964 for (k = 0; k < pass->annotation_count; k++) |
|
965 { |
|
966 freevalue(&pass->annotations[k], f, d); |
|
967 } // for |
|
968 f((void *) pass->annotations, d); |
607 } // for |
969 } // for |
608 f(technique->passes, d); |
970 f((void *) technique->passes, d); |
609 } // for |
971 for (j = 0; j < technique->annotation_count; j++) |
610 |
972 { |
611 f(effect->techniques, d); |
973 freevalue(&technique->annotations[j], f, d); |
612 |
974 } // for |
613 for (i = 0; i < effect->texture_count; i++) |
975 f((void *) technique->annotations, d); |
614 f((void *) effect->textures[i].name, d); |
976 } // for |
615 f(effect->textures, d); |
977 f((void *) effect->techniques, d); |
616 |
978 |
617 for (i = 0; i < effect->shader_count; i++) |
979 /* Free object table */ |
618 MOJOSHADER_freeParseData(effect->shaders[i].shader); |
980 for (i = 0; i < effect->object_count; i++) |
619 f(effect->shaders, d); |
981 { |
620 |
982 MOJOSHADER_effectObject *object = &effect->objects[i]; |
621 f(effect, d); |
983 if (object->type == MOJOSHADER_SYMTYPE_PIXELSHADER |
|
984 || object->type == MOJOSHADER_SYMTYPE_VERTEXSHADER) |
|
985 { |
|
986 if (object->shader.is_preshader) |
|
987 MOJOSHADER_freePreshader(object->shader.preshader, f, d); |
|
988 else |
|
989 MOJOSHADER_freeParseData(object->shader.shader); |
|
990 f((void *) object->shader.params, d); |
|
991 f((void *) object->shader.samplers, d); |
|
992 f((void *) object->shader.preshader_params, d); |
|
993 } // if |
|
994 else if (object->type == MOJOSHADER_SYMTYPE_SAMPLER |
|
995 || object->type == MOJOSHADER_SYMTYPE_SAMPLER1D |
|
996 || object->type == MOJOSHADER_SYMTYPE_SAMPLER2D |
|
997 || object->type == MOJOSHADER_SYMTYPE_SAMPLER3D |
|
998 || object->type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) |
|
999 f((void *) object->mapping.name, d); |
|
1000 else if (object->type == MOJOSHADER_SYMTYPE_STRING) |
|
1001 f((void *) object->string.string, d); |
|
1002 } // for |
|
1003 f((void *) effect->objects, d); |
|
1004 |
|
1005 /* Free base effect structure */ |
|
1006 f((void *) effect, d); |
622 } // MOJOSHADER_freeEffect |
1007 } // MOJOSHADER_freeEffect |
623 |
1008 |
|
1009 |
|
1010 void copyvalue(MOJOSHADER_effectValue *dst, |
|
1011 MOJOSHADER_effectValue *src, |
|
1012 MOJOSHADER_malloc m, |
|
1013 void *d) |
|
1014 { |
|
1015 int i; |
|
1016 uint32 siz = 0; |
|
1017 char *stringcopy = NULL; |
|
1018 |
|
1019 // !!! FIXME: Out of memory check! |
|
1020 #define COPY_STRING(location) \ |
|
1021 if (src->location != NULL) \ |
|
1022 { \ |
|
1023 siz = strlen(src->location) + 1; \ |
|
1024 stringcopy = (char *) m(siz, d); \ |
|
1025 strcpy(stringcopy, src->location); \ |
|
1026 dst->location = stringcopy; \ |
|
1027 } // if |
|
1028 |
|
1029 COPY_STRING(name) |
|
1030 COPY_STRING(semantic) |
|
1031 dst->element_count = src->element_count; |
|
1032 dst->row_count = src->row_count; |
|
1033 dst->column_count = src->column_count; |
|
1034 dst->value_class = src->value_class; |
|
1035 dst->value_type = src->value_type; |
|
1036 dst->value_count = src->value_count; |
|
1037 |
|
1038 if (dst->value_class == MOJOSHADER_SYMCLASS_SCALAR |
|
1039 || dst->value_class == MOJOSHADER_SYMCLASS_VECTOR |
|
1040 || dst->value_class == MOJOSHADER_SYMCLASS_MATRIX_ROWS |
|
1041 || dst->value_class == MOJOSHADER_SYMCLASS_MATRIX_COLUMNS) |
|
1042 { |
|
1043 siz = dst->value_count * 4; |
|
1044 dst->values = m(siz, d); |
|
1045 // !!! FIXME: Out of memory check! |
|
1046 memcpy(dst->values, src->values, siz); |
|
1047 } // if |
|
1048 else if (dst->value_class == MOJOSHADER_SYMCLASS_OBJECT) |
|
1049 { |
|
1050 if (dst->value_type == MOJOSHADER_SYMTYPE_SAMPLER |
|
1051 || dst->value_type == MOJOSHADER_SYMTYPE_SAMPLER1D |
|
1052 || dst->value_type == MOJOSHADER_SYMTYPE_SAMPLER2D |
|
1053 || dst->value_type == MOJOSHADER_SYMTYPE_SAMPLER3D |
|
1054 || dst->value_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) |
|
1055 { |
|
1056 siz = dst->value_count * sizeof (MOJOSHADER_effectSamplerState); |
|
1057 dst->values = m(siz, d); |
|
1058 // !!! FIXME: Out of memory check! |
|
1059 memset(dst->values, '\0', siz); |
|
1060 for (i = 0; i < dst->value_count; i++) |
|
1061 { |
|
1062 dst->valuesSS[i].type = src->valuesSS[i].type; |
|
1063 copyvalue(&dst->valuesSS[i].value, |
|
1064 &src->valuesSS[i].value, |
|
1065 m, d); |
|
1066 } // for |
|
1067 } // if |
|
1068 else |
|
1069 { |
|
1070 siz = dst->value_count * 4; |
|
1071 dst->values = m(siz, d); |
|
1072 // !!! FIXME: Out of memory check! |
|
1073 memcpy(dst->values, src->values, siz); |
|
1074 } // else |
|
1075 } // else if |
|
1076 else if (dst->value_class == MOJOSHADER_SYMCLASS_STRUCT) |
|
1077 { |
|
1078 /* TODO: See readvalue! -flibit */ |
|
1079 } // else if |
|
1080 |
|
1081 #undef COPY_STRING |
|
1082 } // copyvalue |
|
1083 |
|
1084 |
|
1085 void copysymbolinfo(MOJOSHADER_symbolTypeInfo *dst, |
|
1086 MOJOSHADER_symbolTypeInfo *src, |
|
1087 MOJOSHADER_malloc m, |
|
1088 void *d) |
|
1089 { |
|
1090 int i; |
|
1091 uint32 siz; |
|
1092 char *stringcopy; |
|
1093 |
|
1094 dst->parameter_class = src->parameter_class; |
|
1095 dst->parameter_type = src->parameter_type; |
|
1096 dst->rows = src->rows; |
|
1097 dst->columns = src->columns; |
|
1098 dst->elements = src->elements; |
|
1099 dst->member_count = src->member_count; |
|
1100 |
|
1101 if (dst->member_count > 0) |
|
1102 { |
|
1103 siz = sizeof (MOJOSHADER_symbolStructMember) * dst->member_count; |
|
1104 dst->members = (MOJOSHADER_symbolStructMember *) m(siz, d); |
|
1105 // !!! FIXME: Out of memory check! |
|
1106 for (i = 0; i < dst->member_count; i++) |
|
1107 { |
|
1108 if (src->members[i].name != NULL) |
|
1109 { |
|
1110 siz = strlen(src->members[i].name) + 1; |
|
1111 stringcopy = (char *) m(siz, d); |
|
1112 strcpy(stringcopy, src->members[i].name); |
|
1113 dst->members[i].name = stringcopy; |
|
1114 } // if |
|
1115 copysymbolinfo(&dst->members[i].info, &src->members[i].info, m, d); |
|
1116 } // for |
|
1117 } // if |
|
1118 } // copysymbolinfo |
|
1119 |
|
1120 |
|
1121 void copysymbol(MOJOSHADER_symbol *dst, |
|
1122 MOJOSHADER_symbol *src, |
|
1123 MOJOSHADER_malloc m, |
|
1124 void *d) |
|
1125 { |
|
1126 uint32 siz = strlen(src->name) + 1; |
|
1127 char *stringcopy = (char *) m(siz, d); |
|
1128 // !!! FIXME: Out of memory check! |
|
1129 strcpy(stringcopy, src->name); |
|
1130 dst->name = stringcopy; |
|
1131 dst->register_set = src->register_set; |
|
1132 dst->register_index = src->register_index; |
|
1133 dst->register_count = src->register_count; |
|
1134 copysymbolinfo(&dst->info, &src->info, m, d); |
|
1135 } // copysymbol |
|
1136 |
|
1137 |
|
1138 MOJOSHADER_preshader *copypreshader(const MOJOSHADER_preshader *src, |
|
1139 MOJOSHADER_malloc m, |
|
1140 void *d) |
|
1141 { |
|
1142 int i, j; |
|
1143 uint32 siz; |
|
1144 MOJOSHADER_preshader *retval; |
|
1145 |
|
1146 retval = (MOJOSHADER_preshader *) m(sizeof (MOJOSHADER_preshader), d); |
|
1147 // !!! FIXME: Out of memory check! |
|
1148 memset(retval, '\0', sizeof (MOJOSHADER_preshader)); |
|
1149 |
|
1150 siz = sizeof (double) * src->literal_count; |
|
1151 retval->literal_count = src->literal_count; |
|
1152 retval->literals = (double *) m(siz, d); |
|
1153 // !!! FIXME: Out of memory check! |
|
1154 memcpy(retval->literals, src->literals, siz); |
|
1155 |
|
1156 retval->temp_count = src->temp_count; |
|
1157 |
|
1158 siz = sizeof (MOJOSHADER_symbol) * src->symbol_count; |
|
1159 retval->symbol_count = src->symbol_count; |
|
1160 retval->symbols = (MOJOSHADER_symbol *) m(siz, d); |
|
1161 // !!! FIXME: Out of memory check! |
|
1162 memset(retval->symbols, '\0', siz); |
|
1163 |
|
1164 for (i = 0; i < retval->symbol_count; i++) |
|
1165 copysymbol(&retval->symbols[i], &src->symbols[i], m, d); |
|
1166 |
|
1167 siz = sizeof (MOJOSHADER_preshaderInstruction) * src->instruction_count; |
|
1168 retval->instruction_count = src->instruction_count; |
|
1169 retval->instructions = (MOJOSHADER_preshaderInstruction *) m(siz, d); |
|
1170 // !!! FIXME: Out of memory check! |
|
1171 memcpy(retval->instructions, src->instructions, siz); |
|
1172 for (i = 0; i < retval->instruction_count; i++) |
|
1173 for (j = 0; j < retval->instructions[i].operand_count; j++) |
|
1174 { |
|
1175 siz = sizeof (unsigned int) * retval->instructions[i].operands[j].array_register_count; |
|
1176 retval->instructions[i].operands[j].array_registers = (unsigned int *) m(siz, d); |
|
1177 // !!! FIXME: Out of memory check! |
|
1178 memcpy(retval->instructions[i].operands[j].array_registers, |
|
1179 src->instructions[i].operands[j].array_registers, |
|
1180 siz); |
|
1181 } // for |
|
1182 |
|
1183 siz = sizeof (float) * 4 * src->register_count; |
|
1184 retval->register_count = src->register_count; |
|
1185 retval->registers = (float *) m(siz, d); |
|
1186 // !!! FIXME: Out of memory check! |
|
1187 memcpy(retval->registers, src->registers, siz); |
|
1188 |
|
1189 return retval; |
|
1190 } // copypreshader |
|
1191 |
|
1192 |
|
1193 MOJOSHADER_parseData *copyparsedata(const MOJOSHADER_parseData *src, |
|
1194 MOJOSHADER_malloc m, |
|
1195 void *d) |
|
1196 { |
|
1197 int i; |
|
1198 uint32 siz; |
|
1199 char *stringcopy; |
|
1200 MOJOSHADER_parseData *retval; |
|
1201 |
|
1202 retval = (MOJOSHADER_parseData *) m(sizeof (MOJOSHADER_parseData), d); |
|
1203 memset(retval, '\0', sizeof (MOJOSHADER_parseData)); |
|
1204 |
|
1205 /* Copy malloc/free */ |
|
1206 retval->malloc = src->malloc; |
|
1207 retval->free = src->free; |
|
1208 retval->malloc_data = src->malloc_data; |
|
1209 |
|
1210 // !!! FIXME: Out of memory check! |
|
1211 #define COPY_STRING(location) \ |
|
1212 siz = strlen(src->location) + 1; \ |
|
1213 stringcopy = (char *) m(siz, d); \ |
|
1214 strcpy(stringcopy, src->location); \ |
|
1215 retval->location = stringcopy; \ |
|
1216 |
|
1217 /* Copy errors */ |
|
1218 siz = sizeof (MOJOSHADER_error) * src->error_count; |
|
1219 retval->error_count = src->error_count; |
|
1220 retval->errors = (MOJOSHADER_error *) m(siz, d); |
|
1221 // !!! FIXME: Out of memory check! |
|
1222 memset(retval->errors, '\0', siz); |
|
1223 for (i = 0; i < retval->error_count; i++) |
|
1224 { |
|
1225 COPY_STRING(errors[i].error) |
|
1226 COPY_STRING(errors[i].filename) |
|
1227 retval->errors[i].error_position = src->errors[i].error_position; |
|
1228 } // for |
|
1229 |
|
1230 /* Copy profile string constant */ |
|
1231 retval->profile = src->profile; |
|
1232 |
|
1233 /* Copy shader output */ |
|
1234 retval->output_len = src->output_len; |
|
1235 stringcopy = (char *) m(src->output_len, d); |
|
1236 memcpy(stringcopy, src->output, src->output_len); |
|
1237 retval->output = stringcopy; |
|
1238 |
|
1239 /* Copy miscellaneous shader info */ |
|
1240 retval->instruction_count = src->instruction_count; |
|
1241 retval->shader_type = src->shader_type; |
|
1242 retval->major_ver = src->major_ver; |
|
1243 retval->minor_ver = src->minor_ver; |
|
1244 |
|
1245 /* Copy uniforms */ |
|
1246 siz = sizeof (MOJOSHADER_uniform) * src->uniform_count; |
|
1247 retval->uniform_count = src->uniform_count; |
|
1248 retval->uniforms = (MOJOSHADER_uniform *) m(siz, d); |
|
1249 // !!! FIXME: Out of memory check! |
|
1250 memset(retval->uniforms, '\0', siz); |
|
1251 for (i = 0; i < retval->uniform_count; i++) |
|
1252 { |
|
1253 retval->uniforms[i].type = src->uniforms[i].type; |
|
1254 retval->uniforms[i].index = src->uniforms[i].index; |
|
1255 retval->uniforms[i].array_count = src->uniforms[i].array_count; |
|
1256 retval->uniforms[i].constant = src->uniforms[i].constant; |
|
1257 COPY_STRING(uniforms[i].name) |
|
1258 } // for |
|
1259 |
|
1260 /* Copy constants */ |
|
1261 siz = sizeof (MOJOSHADER_constant) * src->constant_count; |
|
1262 retval->constant_count = src->constant_count; |
|
1263 retval->constants = (MOJOSHADER_constant *) m(siz, d); |
|
1264 // !!! FIXME: Out of memory check! |
|
1265 memcpy(retval->constants, src->constants, siz); |
|
1266 |
|
1267 /* Copy samplers */ |
|
1268 siz = sizeof (MOJOSHADER_sampler) * src->sampler_count; |
|
1269 retval->sampler_count = src->sampler_count; |
|
1270 retval->samplers = (MOJOSHADER_sampler *) m(siz, d); |
|
1271 // !!! FIXME: Out of memory check! |
|
1272 memset(retval->samplers, '\0', siz); |
|
1273 for (i = 0; i < retval->sampler_count; i++) |
|
1274 { |
|
1275 retval->samplers[i].type = src->samplers[i].type; |
|
1276 retval->samplers[i].index = src->samplers[i].index; |
|
1277 COPY_STRING(samplers[i].name) |
|
1278 retval->samplers[i].texbem = src->samplers[i].texbem; |
|
1279 } // for |
|
1280 |
|
1281 /* Copy attributes */ |
|
1282 siz = sizeof (MOJOSHADER_attribute) * src->attribute_count; |
|
1283 retval->attribute_count = src->attribute_count; |
|
1284 retval->attributes = (MOJOSHADER_attribute *) m(siz, d); |
|
1285 // !!! FIXME: Out of memory check! |
|
1286 memset(retval->attributes, '\0', siz); |
|
1287 for (i = 0; i < retval->attribute_count; i++) |
|
1288 { |
|
1289 retval->attributes[i].usage = src->attributes[i].usage; |
|
1290 retval->attributes[i].index = src->attributes[i].index; |
|
1291 COPY_STRING(attributes[i].name) |
|
1292 } // for |
|
1293 |
|
1294 /* Copy outputs */ |
|
1295 siz = sizeof (MOJOSHADER_attribute) * src->output_count; |
|
1296 retval->output_count = src->output_count; |
|
1297 retval->outputs = (MOJOSHADER_attribute *) m(siz, d); |
|
1298 // !!! FIXME: Out of memory check! |
|
1299 memset(retval->outputs, '\0', siz); |
|
1300 for (i = 0; i < retval->output_count; i++) |
|
1301 { |
|
1302 retval->outputs[i].usage = src->outputs[i].usage; |
|
1303 retval->outputs[i].index = src->outputs[i].index; |
|
1304 COPY_STRING(outputs[i].name) |
|
1305 } // for |
|
1306 |
|
1307 #undef COPY_STRING |
|
1308 |
|
1309 /* Copy swizzles */ |
|
1310 siz = sizeof (MOJOSHADER_swizzle) * src->swizzle_count; |
|
1311 retval->swizzle_count = src->swizzle_count; |
|
1312 retval->swizzles = (MOJOSHADER_swizzle *) m(siz, d); |
|
1313 // !!! FIXME: Out of memory check! |
|
1314 memcpy(retval->swizzles, src->swizzles, siz); |
|
1315 |
|
1316 /* Copy symbols */ |
|
1317 siz = sizeof (MOJOSHADER_symbol) * src->symbol_count; |
|
1318 retval->symbol_count = src->symbol_count; |
|
1319 retval->symbols = (MOJOSHADER_symbol *) m(siz, d); |
|
1320 // !!! FIXME: Out of memory check! |
|
1321 memset(retval->symbols, '\0', siz); |
|
1322 for (i = 0; i < retval->symbol_count; i++) |
|
1323 copysymbol(&retval->symbols[i], &src->symbols[i], m, d); |
|
1324 |
|
1325 /* Copy preshader */ |
|
1326 if (src->preshader != NULL) |
|
1327 retval->preshader = copypreshader(src->preshader, m, d); |
|
1328 |
|
1329 return retval; |
|
1330 } // copyparsedata |
|
1331 |
|
1332 |
|
1333 MOJOSHADER_effect *MOJOSHADER_cloneEffect(const MOJOSHADER_effect *effect) |
|
1334 { |
|
1335 int i, j, k; |
|
1336 MOJOSHADER_effect *clone; |
|
1337 MOJOSHADER_malloc m = effect->malloc; |
|
1338 void *d = effect->malloc_data; |
|
1339 uint32 siz = 0; |
|
1340 char *stringcopy = NULL; |
|
1341 uint32 curSampler; |
|
1342 |
|
1343 if ((effect == NULL) || (effect == &MOJOSHADER_out_of_mem_effect)) |
|
1344 return NULL; // no-op. |
|
1345 |
|
1346 clone = (MOJOSHADER_effect *) m(sizeof (MOJOSHADER_effect), d); |
|
1347 if (clone == NULL) |
|
1348 return NULL; // Maybe out_of_mem_effect instead? |
|
1349 memset(clone, '\0', sizeof (MOJOSHADER_effect)); |
|
1350 |
|
1351 /* Copy malloc/free */ |
|
1352 clone->malloc = effect->malloc; |
|
1353 clone->free = effect->free; |
|
1354 clone->malloc_data = effect->malloc_data; |
|
1355 |
|
1356 #define COPY_STRING(location) \ |
|
1357 siz = strlen(effect->location) + 1; \ |
|
1358 stringcopy = (char *) m(siz, d); \ |
|
1359 if (stringcopy == NULL) \ |
|
1360 goto cloneEffect_outOfMemory; \ |
|
1361 strcpy(stringcopy, effect->location); \ |
|
1362 clone->location = stringcopy; \ |
|
1363 |
|
1364 /* Copy errors */ |
|
1365 siz = sizeof (MOJOSHADER_error) * effect->error_count; |
|
1366 clone->error_count = effect->error_count; |
|
1367 clone->errors = (MOJOSHADER_error *) m(siz, d); |
|
1368 if (clone->errors == NULL) |
|
1369 goto cloneEffect_outOfMemory; |
|
1370 memset(clone->errors, '\0', siz); |
|
1371 for (i = 0; i < clone->error_count; i++) |
|
1372 { |
|
1373 COPY_STRING(errors[i].error) |
|
1374 COPY_STRING(errors[i].filename) |
|
1375 clone->errors[i].error_position = effect->errors[i].error_position; |
|
1376 } // for |
|
1377 |
|
1378 /* Copy profile string */ |
|
1379 COPY_STRING(profile) |
|
1380 |
|
1381 /* Copy parameters */ |
|
1382 siz = sizeof (MOJOSHADER_effectParam) * effect->param_count; |
|
1383 clone->param_count = effect->param_count; |
|
1384 clone->params = (MOJOSHADER_effectParam *) m(siz, d); |
|
1385 if (clone->params == NULL) |
|
1386 goto cloneEffect_outOfMemory; |
|
1387 memset(clone->params, '\0', siz); |
|
1388 for (i = 0; i < clone->param_count; i++) |
|
1389 { |
|
1390 copyvalue(&clone->params[i].value, &effect->params[i].value, m, d); |
|
1391 |
|
1392 /* Copy parameter annotations */ |
|
1393 siz = sizeof (MOJOSHADER_effectAnnotation) * effect->params[i].annotation_count; |
|
1394 clone->params[i].annotation_count = effect->params[i].annotation_count; |
|
1395 clone->params[i].annotations = (MOJOSHADER_effectAnnotation *) m(siz, d); |
|
1396 if (clone->params[i].annotations == NULL) |
|
1397 goto cloneEffect_outOfMemory; |
|
1398 memset(clone->params[i].annotations, '\0', siz); |
|
1399 for (j = 0; j < clone->params[i].annotation_count; j++) |
|
1400 copyvalue(&clone->params[i].annotations[j], |
|
1401 &effect->params[i].annotations[j], |
|
1402 m, d); |
|
1403 } // for |
|
1404 |
|
1405 /* Copy techniques */ |
|
1406 siz = sizeof (MOJOSHADER_effectTechnique) * effect->technique_count; |
|
1407 clone->technique_count = effect->technique_count; |
|
1408 clone->techniques = (MOJOSHADER_effectTechnique *) m(siz, d); |
|
1409 if (clone->techniques == NULL) |
|
1410 goto cloneEffect_outOfMemory; |
|
1411 memset(clone->techniques, '\0', siz); |
|
1412 for (i = 0; i < clone->technique_count; i++) |
|
1413 { |
|
1414 COPY_STRING(techniques[i].name) |
|
1415 |
|
1416 /* Copy passes */ |
|
1417 siz = sizeof (MOJOSHADER_effectPass) * effect->techniques[i].pass_count; |
|
1418 clone->techniques[i].pass_count = effect->techniques[i].pass_count; |
|
1419 clone->techniques[i].passes = (MOJOSHADER_effectPass *) m(siz, d); |
|
1420 if (clone->techniques[i].passes == NULL) |
|
1421 goto cloneEffect_outOfMemory; |
|
1422 memset(clone->techniques[i].passes, '\0', siz); |
|
1423 for (j = 0; j < clone->techniques[i].pass_count; j++) |
|
1424 { |
|
1425 COPY_STRING(techniques[i].passes[j].name) |
|
1426 |
|
1427 /* Copy pass states */ |
|
1428 siz = sizeof (MOJOSHADER_effectState) * effect->techniques[i].passes[j].state_count; |
|
1429 clone->techniques[i].passes[j].state_count = effect->techniques[i].passes[j].state_count; |
|
1430 clone->techniques[i].passes[j].states = (MOJOSHADER_effectState *) m(siz, d); |
|
1431 if (clone->techniques[i].passes[j].states == NULL) |
|
1432 goto cloneEffect_outOfMemory; |
|
1433 memset(clone->techniques[i].passes[j].states, '\0', siz); |
|
1434 for (k = 0; k < clone->techniques[i].passes[j].state_count; k++) |
|
1435 { |
|
1436 clone->techniques[i].passes[j].states[k].type = effect->techniques[i].passes[j].states[k].type; |
|
1437 copyvalue(&clone->techniques[i].passes[j].states[k].value, |
|
1438 &effect->techniques[i].passes[j].states[k].value, |
|
1439 m, d); |
|
1440 } // for |
|
1441 |
|
1442 /* Copy pass annotations */ |
|
1443 siz = sizeof (MOJOSHADER_effectAnnotation) * effect->techniques[i].passes[j].annotation_count; |
|
1444 clone->techniques[i].passes[j].annotation_count = effect->techniques[i].passes[j].annotation_count; |
|
1445 clone->techniques[i].passes[j].annotations = (MOJOSHADER_effectAnnotation *) m(siz, d); |
|
1446 if (clone->techniques[i].passes[j].annotations == NULL) |
|
1447 goto cloneEffect_outOfMemory; |
|
1448 memset(clone->techniques[i].passes[j].annotations, '\0', siz); |
|
1449 for (k = 0; k < clone->techniques[i].passes[j].annotation_count; k++) |
|
1450 copyvalue(&clone->techniques[i].passes[j].annotations[k], |
|
1451 &effect->techniques[i].passes[j].annotations[k], |
|
1452 m, d); |
|
1453 } // for |
|
1454 |
|
1455 /* Copy technique annotations */ |
|
1456 siz = sizeof (MOJOSHADER_effectAnnotation) * effect->techniques[i].annotation_count; |
|
1457 clone->techniques[i].annotation_count = effect->techniques[i].annotation_count; |
|
1458 clone->techniques[i].annotations = (MOJOSHADER_effectAnnotation *) m(siz, d); |
|
1459 if (clone->techniques[i].annotations == NULL) |
|
1460 goto cloneEffect_outOfMemory; |
|
1461 memset(clone->techniques[i].annotations, '\0', siz); |
|
1462 for (j = 0; j < clone->techniques[i].annotation_count; j++) |
|
1463 copyvalue(&clone->techniques[i].annotations[j], |
|
1464 &effect->techniques[i].annotations[j], |
|
1465 m, d); |
|
1466 } // for |
|
1467 |
|
1468 /* Copy the current technique/pass */ |
|
1469 for (i = 0; i < effect->technique_count; i++) |
|
1470 if (&effect->techniques[i] == effect->current_technique) |
|
1471 { |
|
1472 clone->current_technique = &clone->techniques[i]; |
|
1473 break; |
|
1474 } // if |
|
1475 assert(clone->current_technique != NULL); |
|
1476 clone->current_pass = effect->current_pass; |
|
1477 assert(clone->current_pass == -1); |
|
1478 |
|
1479 /* Copy object table */ |
|
1480 siz = sizeof (MOJOSHADER_effectObject) * effect->object_count; |
|
1481 clone->object_count = effect->object_count; |
|
1482 clone->objects = (MOJOSHADER_effectObject *) m(siz, d); |
|
1483 if (clone->objects == NULL) |
|
1484 goto cloneEffect_outOfMemory; |
|
1485 memset(clone->objects, '\0', siz); |
|
1486 for (i = 0; i < clone->object_count; i++) |
|
1487 { |
|
1488 clone->objects[i].type = effect->objects[i].type; |
|
1489 if (clone->objects[i].type == MOJOSHADER_SYMTYPE_PIXELSHADER |
|
1490 || clone->objects[i].type == MOJOSHADER_SYMTYPE_VERTEXSHADER) |
|
1491 { |
|
1492 clone->objects[i].shader.technique = effect->objects[i].shader.technique; |
|
1493 clone->objects[i].shader.pass = effect->objects[i].shader.pass; |
|
1494 clone->objects[i].shader.is_preshader = effect->objects[i].shader.is_preshader; |
|
1495 siz = sizeof (uint32) * effect->objects[i].shader.preshader_param_count; |
|
1496 clone->objects[i].shader.preshader_param_count = effect->objects[i].shader.preshader_param_count; |
|
1497 clone->objects[i].shader.preshader_params = (uint32 *) m(siz, d); |
|
1498 memcpy(clone->objects[i].shader.preshader_params, |
|
1499 effect->objects[i].shader.preshader_params, |
|
1500 siz); |
|
1501 siz = sizeof (uint32) * effect->objects[i].shader.param_count; |
|
1502 clone->objects[i].shader.param_count = effect->objects[i].shader.param_count; |
|
1503 clone->objects[i].shader.params = (uint32 *) m(siz, d); |
|
1504 memcpy(clone->objects[i].shader.params, |
|
1505 effect->objects[i].shader.params, |
|
1506 siz); |
|
1507 |
|
1508 if (clone->objects[i].shader.is_preshader) |
|
1509 { |
|
1510 clone->objects[i].shader.preshader = copypreshader(effect->objects[i].shader.preshader, |
|
1511 m, d); |
|
1512 continue; |
|
1513 } // if |
|
1514 |
|
1515 clone->objects[i].shader.shader = copyparsedata(effect->objects[i].shader.shader, |
|
1516 m, d); |
|
1517 |
|
1518 siz = sizeof (MOJOSHADER_samplerStateRegister) * effect->objects[i].shader.sampler_count; |
|
1519 clone->objects[i].shader.sampler_count = effect->objects[i].shader.sampler_count; |
|
1520 clone->objects[i].shader.samplers = (MOJOSHADER_samplerStateRegister *) m(siz, d); |
|
1521 if (clone->objects[i].shader.samplers == NULL) |
|
1522 goto cloneEffect_outOfMemory; |
|
1523 curSampler = 0; |
|
1524 for (j = 0; j < clone->objects[i].shader.shader->symbol_count; j++) |
|
1525 if (clone->objects[i].shader.shader->symbols[j].register_set == MOJOSHADER_SYMREGSET_SAMPLER) |
|
1526 { |
|
1527 clone->objects[i].shader.samplers[curSampler].sampler_name = clone->objects[i].shader.shader->symbols[j].name; |
|
1528 clone->objects[i].shader.samplers[curSampler].sampler_register = clone->objects[i].shader.shader->symbols[j].register_index; |
|
1529 clone->objects[i].shader.samplers[curSampler].sampler_state_count = clone->params[clone->objects[i].shader.params[j]].value.value_count; |
|
1530 clone->objects[i].shader.samplers[curSampler].sampler_states = clone->params[clone->objects[i].shader.params[j]].value.valuesSS; |
|
1531 curSampler++; |
|
1532 } // if |
|
1533 } // if |
|
1534 else if (clone->objects[i].type == MOJOSHADER_SYMTYPE_SAMPLER |
|
1535 || clone->objects[i].type == MOJOSHADER_SYMTYPE_SAMPLER1D |
|
1536 || clone->objects[i].type == MOJOSHADER_SYMTYPE_SAMPLER2D |
|
1537 || clone->objects[i].type == MOJOSHADER_SYMTYPE_SAMPLER3D |
|
1538 || clone->objects[i].type == MOJOSHADER_SYMTYPE_SAMPLERCUBE) |
|
1539 { |
|
1540 COPY_STRING(objects[i].mapping.name) |
|
1541 } // else if |
|
1542 else if (clone->objects[i].type == MOJOSHADER_SYMTYPE_STRING) |
|
1543 { |
|
1544 COPY_STRING(objects[i].string.string) |
|
1545 } // else if |
|
1546 } // for |
|
1547 |
|
1548 #undef COPY_STRING |
|
1549 |
|
1550 return clone; |
|
1551 |
|
1552 cloneEffect_outOfMemory: |
|
1553 MOJOSHADER_freeEffect(clone); |
|
1554 return NULL; |
|
1555 } // MOJOSHADER_cloneEffect |
|
1556 |
|
1557 |
|
1558 void MOJOSHADER_effectSetRawValueHandle(const MOJOSHADER_effectParam *parameter, |
|
1559 const void *data, |
|
1560 const unsigned int offset, |
|
1561 const unsigned int len) |
|
1562 { |
|
1563 // !!! FIXME: uint32* case is arbitary, for Win32 -flibit |
|
1564 memcpy((uint32 *) parameter->value.values + offset, data, len); |
|
1565 } // MOJOSHADER_effectSetRawValueHandle |
|
1566 |
|
1567 |
|
1568 void MOJOSHADER_effectSetRawValueName(const MOJOSHADER_effect *effect, |
|
1569 const char *name, |
|
1570 const void *data, |
|
1571 const unsigned int offset, |
|
1572 const unsigned int len) |
|
1573 { |
|
1574 int i; |
|
1575 for (i = 0; i < effect->param_count; i++) |
|
1576 { |
|
1577 if (strcmp(name, effect->params[i].value.name) == 0) |
|
1578 { |
|
1579 // !!! FIXME: uint32* case is arbitary, for Win32 -flibit |
|
1580 memcpy((uint32 *) effect->params[i].value.values + offset, data, len); |
|
1581 return; |
|
1582 } // if |
|
1583 } // for |
|
1584 assert(0 && "Effect parameter not found!"); |
|
1585 } // MOJOSHADER_effectSetRawValueName |
|
1586 |
|
1587 |
|
1588 const MOJOSHADER_effectTechnique *MOJOSHADER_effectGetCurrentTechnique(const MOJOSHADER_effect *effect) |
|
1589 { |
|
1590 return effect->current_technique; |
|
1591 } // MOJOSHADER_effectGetCurrentTechnique |
|
1592 |
|
1593 |
|
1594 void MOJOSHADER_effectSetTechnique(MOJOSHADER_effect *effect, |
|
1595 const MOJOSHADER_effectTechnique *technique) |
|
1596 { |
|
1597 int i; |
|
1598 for (i = 0; i < effect->technique_count; i++) |
|
1599 { |
|
1600 if (technique == &effect->techniques[i]) |
|
1601 { |
|
1602 effect->current_technique = technique; |
|
1603 return; |
|
1604 } // if |
|
1605 } // for |
|
1606 assert(0 && "Technique is not part of this effect!"); |
|
1607 } // MOJOSHADER_effectSetTechnique |
|
1608 |
|
1609 |
|
1610 const MOJOSHADER_effectTechnique *MOJOSHADER_effectFindNextValidTechnique(const MOJOSHADER_effect *effect, |
|
1611 const MOJOSHADER_effectTechnique *technique |
|
1612 ) |
|
1613 { |
|
1614 int i; |
|
1615 if (technique == NULL) |
|
1616 return &effect->techniques[0]; |
|
1617 for (i = 0; i < effect->technique_count; i++) |
|
1618 { |
|
1619 if (technique == &effect->techniques[i]) |
|
1620 { |
|
1621 if (i == effect->technique_count - 1) |
|
1622 return NULL; /* We were passed the last technique! */ |
|
1623 return &effect->techniques[i + 1]; |
|
1624 } // if |
|
1625 } // for |
|
1626 assert(0 && "Technique is not part of this effect!"); |
|
1627 } // MOJOSHADER_effectFindNextValidTechnique |
|
1628 |
|
1629 #endif // MOJOSHADER_EFFECT_SUPPORT |
|
1630 |
624 // end of mojoshader_effects.c ... |
1631 // end of mojoshader_effects.c ... |
625 |
1632 |