static struct gl_vertex_program * search_cache(struct tnl_cache *cache, GLuint hash, const void *key, GLuint keysize) { struct tnl_cache_item *c; for (c = cache->items[hash % cache->size]; c; c = c->next) { if (c->hash == hash && _mesa_memcmp(c->key, key, keysize) == 0) return c->prog; } return NULL; }
struct r300_vertex_program * r300SelectAndTranslateVertexShader(GLcontext *ctx) { r300ContextPtr r300 = R300_CONTEXT(ctx); struct r300_vertex_program_key wanted_key = { 0 }; struct r300_vertex_program_cont *vpc; struct r300_vertex_program *vp; vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; if (!r300->selected_fp) { /* This can happen when GetProgramiv is called to check * whether the program runs natively. * * To be honest, this is not a very good solution, * but solving the problem of reporting good values * for those queries is tough anyway considering that * we recompile vertex programs based on the precise * fragment program that is in use. */ r300SelectAndTranslateFragmentShader(ctx); } wanted_key.FpReads = r300->selected_fp->InputsRead; wanted_key.FogAttr = r300->selected_fp->fog_attr; wanted_key.WPosAttr = r300->selected_fp->wpos_attr; for (vp = vpc->progs; vp; vp = vp->next) { if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key)) == 0) { return r300->selected_vp = vp; } } vp = build_program(ctx, &wanted_key, &vpc->mesa_program); vp->next = vpc->progs; vpc->progs = vp; return r300->selected_vp = vp; }
void r300TranslateFragmentShader(r300ContextPtr r300, struct r300_fragment_program *fp) { struct r300_fragment_program_external_state state; build_state(r300, fp, &state); if (_mesa_memcmp(&fp->state, &state, sizeof(state))) { /* TODO: cache compiled programs */ fp->translated = GL_FALSE; _mesa_memcpy(&fp->state, &state, sizeof(state)); } if (!fp->translated) { struct r300_fragment_program_compiler compiler; compiler.r300 = r300; compiler.fp = fp; compiler.code = &fp->code; compiler.program = _mesa_clone_program(r300->radeon.glCtx, &fp->mesa_program.Base); if (RADEON_DEBUG & DEBUG_PIXEL) { _mesa_printf("Fragment Program: Initial program:\n"); _mesa_print_program(compiler.program); } insert_WPOS_trailer(&compiler); struct radeon_program_transformation transformations[] = { { &transform_TEX, &compiler }, { &radeonTransformALU, 0 }, { &radeonTransformTrigSimple, 0 } }; radeonLocalTransform( r300->radeon.glCtx, compiler.program, 3, transformations); if (RADEON_DEBUG & DEBUG_PIXEL) { _mesa_printf("Fragment Program: After native rewrite:\n"); _mesa_print_program(compiler.program); } struct radeon_nqssadce_descr nqssadce = { .Init = &nqssadce_init, .IsNativeSwizzle = &r300FPIsNativeSwizzle, .BuildSwizzle = &r300FPBuildSwizzle, .RewriteDepthOut = GL_TRUE }; radeonNqssaDce(r300->radeon.glCtx, compiler.program, &nqssadce); if (RADEON_DEBUG & DEBUG_PIXEL) { _mesa_printf("Compiler: after NqSSA-DCE:\n"); _mesa_print_program(compiler.program); } if (!r300FragmentProgramEmit(&compiler)) fp->error = GL_TRUE; /* Subtle: Rescue any parameters that have been added during transformations */ _mesa_free_parameter_list(fp->mesa_program.Base.Parameters); fp->mesa_program.Base.Parameters = compiler.program->Parameters; compiler.program->Parameters = 0; _mesa_reference_program(r300->radeon.glCtx, &compiler.program, NULL); if (!fp->error) fp->translated = GL_TRUE; if (fp->error || (RADEON_DEBUG & DEBUG_PIXEL)) r300FragmentProgramDump(fp, &fp->code); r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM); } update_params(r300, fp); }