OSDN Git Service

05f46ad0607132f912b07fca5030371ab9e5b39b
[android-x86/external-mesa.git] / src / mesa / drivers / dri / r300 / r300_fragprog_common.c
1 /*
2  * Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com>
3  *
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial
16  * portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27
28 /**
29  * \file
30  *
31  * Fragment program compiler. Perform transformations on the intermediate
32  * representation until the program is in a form where we can translate
33  * it more or less directly into machine-readable form.
34  *
35  * \author Ben Skeggs <darktama@iinet.net.au>
36  * \author Jerome Glisse <j.glisse@gmail.com>
37  */
38
39 #include "r300_fragprog_common.h"
40
41 #include "shader/program.h"
42 #include "shader/prog_parameter.h"
43 #include "shader/prog_print.h"
44
45 #include "compiler/radeon_compiler.h"
46
47 #include "r300_state.h"
48
49
50 static GLuint build_dtm(GLuint depthmode)
51 {
52         switch(depthmode) {
53         default:
54         case GL_LUMINANCE: return 0;
55         case GL_INTENSITY: return 1;
56         case GL_ALPHA: return 2;
57         }
58 }
59
60 static GLuint build_func(GLuint comparefunc)
61 {
62         return comparefunc - GL_NEVER;
63 }
64
65 /**
66  * Collect all external state that is relevant for compiling the given
67  * fragment program.
68  */
69 static void build_state(
70         r300ContextPtr r300,
71         struct gl_fragment_program *fp,
72         struct r300_fragment_program_external_state *state)
73 {
74         int unit;
75
76         _mesa_bzero(state, sizeof(*state));
77
78         for(unit = 0; unit < 16; ++unit) {
79                 if (fp->Base.ShadowSamplers & (1 << unit)) {
80                         struct gl_texture_object* tex = r300->radeon.glCtx->Texture.Unit[unit]._Current;
81
82                         state->unit[unit].depth_texture_mode = build_dtm(tex->DepthMode);
83                         state->unit[unit].texture_compare_func = build_func(tex->CompareFunc);
84                 }
85         }
86 }
87
88
89 static void translate_fragment_program(GLcontext *ctx, struct r300_fragment_program_cont *cont, struct r300_fragment_program *fp)
90 {
91         r300ContextPtr r300 = R300_CONTEXT(ctx);
92         struct r300_fragment_program_compiler compiler;
93
94         rc_init(&compiler.Base);
95         compiler.Base.Debug = (RADEON_DEBUG & DEBUG_PIXEL) ? GL_TRUE : GL_FALSE;
96
97         compiler.code = &fp->code;
98         compiler.state = fp->state;
99         compiler.is_r500 = (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) ? GL_TRUE : GL_FALSE;
100
101         if (compiler.Base.Debug) {
102                 fflush(stdout);
103                 _mesa_printf("Fragment Program: Initial program:\n");
104                 _mesa_print_program(&cont->Base.Base);
105                 fflush(stdout);
106         }
107
108         rc_mesa_to_rc_program(&compiler.Base, &cont->Base.Base);
109
110         r3xx_compile_fragment_program(&compiler);
111         fp->error = compiler.Base.Error;
112
113         fp->InputsRead = compiler.Base.Program.InputsRead;
114
115         rc_destroy(&compiler.Base);
116 }
117
118 struct r300_fragment_program *r300SelectAndTranslateFragmentShader(GLcontext *ctx)
119 {
120         r300ContextPtr r300 = R300_CONTEXT(ctx);
121         struct r300_fragment_program_cont *fp_list;
122         struct r300_fragment_program *fp;
123         struct r300_fragment_program_external_state state;
124
125         fp_list = (struct r300_fragment_program_cont *)ctx->FragmentProgram._Current;
126         build_state(r300, ctx->FragmentProgram._Current, &state);
127
128         fp = fp_list->progs;
129         while (fp) {
130                 if (_mesa_memcmp(&fp->state, &state, sizeof(state)) == 0) {
131                         return r300->selected_fp = fp;
132                 }
133                 fp = fp->next;
134         }
135
136         fp = _mesa_calloc(sizeof(struct r300_fragment_program));
137
138         fp->state = state;
139
140         fp->next = fp_list->progs;
141         fp_list->progs = fp;
142
143         translate_fragment_program(ctx, fp_list, fp);
144
145         return r300->selected_fp = fp;
146 }