OSDN Git Service

i965: avoid unnecessary calls to brw_wm_is_glsl()
[android-x86/external-mesa.git] / src / mesa / drivers / dri / i965 / brw_wm.c
1 /*
2  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3  Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4  develop this 3D driver.
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   * Authors:
29   *   Keith Whitwell <keith@tungstengraphics.com>
30   */
31              
32 #include "main/texformat.h"
33 #include "brw_context.h"
34 #include "brw_util.h"
35 #include "brw_wm.h"
36 #include "brw_state.h"
37
38
39 /** Return number of src args for given instruction */
40 GLuint brw_wm_nr_args( GLuint opcode )
41 {
42    switch (opcode) {
43    case WM_PIXELXY:
44    case WM_CINTERP:
45    case WM_WPOSXY:
46       return 1;
47    case WM_LINTERP:
48    case WM_DELTAXY:
49    case WM_PIXELW:
50       return 2;
51    case WM_FB_WRITE:
52    case WM_PINTERP:
53       return 3;
54    default:
55       assert(opcode < MAX_OPCODE);
56       return _mesa_num_inst_src_regs(opcode);
57    }
58 }
59
60
61 GLuint brw_wm_is_scalar_result( GLuint opcode )
62 {
63    switch (opcode) {
64    case OPCODE_COS:
65    case OPCODE_EX2:
66    case OPCODE_LG2:
67    case OPCODE_POW:
68    case OPCODE_RCP:
69    case OPCODE_RSQ:
70    case OPCODE_SIN:
71    case OPCODE_DP3:
72    case OPCODE_DP4:
73    case OPCODE_DPH:
74    case OPCODE_DST:
75       return 1;
76       
77    default:
78       return 0;
79    }
80 }
81
82
83 /**
84  * Do GPU code generation for non-GLSL shader.  non-GLSL shaders have
85  * no flow control instructions so we can more readily do SSA-style
86  * optimizations.
87  */
88 static void
89 brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
90 {
91    /* Augment fragment program.  Add instructions for pre- and
92     * post-fragment-program tasks such as interpolation and fogging.
93     */
94    brw_wm_pass_fp(c);
95
96    /* Translate to intermediate representation.  Build register usage
97     * chains.
98     */
99    brw_wm_pass0(c);
100
101    /* Dead code removal.
102     */
103    brw_wm_pass1(c);
104
105    /* Register allocation.
106     */
107    c->grf_limit = BRW_WM_MAX_GRF / 2;
108
109    brw_wm_pass2(c);
110
111    c->prog_data.total_grf = c->max_wm_grf;
112    if (c->last_scratch) {
113       c->prog_data.total_scratch = c->last_scratch + 0x40;
114    }
115    else {
116       c->prog_data.total_scratch = 0;
117    }
118
119    /* Emit GEN4 code.
120     */
121    brw_wm_emit(c);
122 }
123
124
125 /**
126  * All Mesa program -> GPU code generation goes through this function.
127  * Depending on the instructions used (i.e. flow control instructions)
128  * we'll use one of two code generators.
129  */
130 static void do_wm_prog( struct brw_context *brw,
131                         struct brw_fragment_program *fp, 
132                         struct brw_wm_prog_key *key)
133 {
134    struct brw_wm_compile *c;
135    const GLuint *program;
136    GLuint program_size;
137
138    c = brw->wm.compile_data;
139    if (c == NULL) {
140       brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data));
141       c = brw->wm.compile_data;
142    } else {
143       memset(c, 0, sizeof(*brw->wm.compile_data));
144    }
145    memcpy(&c->key, key, sizeof(*key));
146
147    c->fp = fp;
148    c->env_param = brw->intel.ctx.FragmentProgram.Parameters;
149
150    brw_init_compile(brw, &c->func);
151
152    /* temporary sanity check assertion */
153    ASSERT(fp->isGLSL == brw_wm_is_glsl(&c->fp->program));
154
155    /*
156     * Shader which use GLSL features such as flow control are handled
157     * differently from "simple" shaders.
158     */
159    if (fp->isGLSL) {
160       brw_wm_glsl_emit(brw, c);
161    }
162    else {
163       brw_wm_non_glsl_emit(brw, c);
164    }
165
166    if (INTEL_DEBUG & DEBUG_WM)
167       fprintf(stderr, "\n");
168
169    /* get the program
170     */
171    program = brw_get_program(&c->func, &program_size);
172
173    dri_bo_unreference(brw->wm.prog_bo);
174    brw->wm.prog_bo = brw_upload_cache( &brw->cache, BRW_WM_PROG,
175                                        &c->key, sizeof(c->key),
176                                        NULL, 0,
177                                        program, program_size,
178                                        &c->prog_data,
179                                        &brw->wm.prog_data );
180 }
181
182
183
184 static void brw_wm_populate_key( struct brw_context *brw,
185                                  struct brw_wm_prog_key *key )
186 {
187    GLcontext *ctx = &brw->intel.ctx;
188    /* BRW_NEW_FRAGMENT_PROGRAM */
189    const struct brw_fragment_program *fp = 
190       (struct brw_fragment_program *)brw->fragment_program;
191    GLuint lookup = 0;
192    GLuint line_aa;
193    GLuint i;
194
195    memset(key, 0, sizeof(*key));
196
197    /* Build the index for table lookup
198     */
199    /* _NEW_COLOR */
200    if (fp->program.UsesKill ||
201        ctx->Color.AlphaEnabled)
202       lookup |= IZ_PS_KILL_ALPHATEST_BIT;
203
204    if (fp->program.Base.OutputsWritten & (1<<FRAG_RESULT_DEPTH))
205       lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
206
207    /* _NEW_DEPTH */
208    if (ctx->Depth.Test)
209       lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
210
211    if (ctx->Depth.Test &&  
212        ctx->Depth.Mask) /* ?? */
213       lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
214
215    /* _NEW_STENCIL */
216    if (ctx->Stencil._Enabled) {
217       lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
218
219       if (ctx->Stencil.WriteMask[0] ||
220           ctx->Stencil.WriteMask[ctx->Stencil._BackFace])
221          lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
222    }
223
224    line_aa = AA_NEVER;
225
226    /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
227    if (ctx->Line.SmoothFlag) {
228       if (brw->intel.reduced_primitive == GL_LINES) {
229          line_aa = AA_ALWAYS;
230       }
231       else if (brw->intel.reduced_primitive == GL_TRIANGLES) {
232          if (ctx->Polygon.FrontMode == GL_LINE) {
233             line_aa = AA_SOMETIMES;
234
235             if (ctx->Polygon.BackMode == GL_LINE ||
236                 (ctx->Polygon.CullFlag &&
237                  ctx->Polygon.CullFaceMode == GL_BACK))
238                line_aa = AA_ALWAYS;
239          }
240          else if (ctx->Polygon.BackMode == GL_LINE) {
241             line_aa = AA_SOMETIMES;
242
243             if ((ctx->Polygon.CullFlag &&
244                  ctx->Polygon.CullFaceMode == GL_FRONT))
245                line_aa = AA_ALWAYS;
246          }
247       }
248    }
249          
250    brw_wm_lookup_iz(line_aa,
251                     lookup,
252                     key);
253
254
255    /* BRW_NEW_WM_INPUT_DIMENSIONS */
256    key->projtex_mask = brw->wm.input_size_masks[4-1] >> (FRAG_ATTRIB_TEX0 - FRAG_ATTRIB_WPOS); 
257
258    /* _NEW_LIGHT */
259    key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
260
261    /* _NEW_TEXTURE */
262    for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
263       const struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
264
265       if (unit->_ReallyEnabled) {
266          const struct gl_texture_object *t = unit->_Current;
267          const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
268          if (img->InternalFormat == GL_YCBCR_MESA) {
269             key->yuvtex_mask |= 1 << i;
270             if (img->TexFormat->MesaFormat == MESA_FORMAT_YCBCR)
271                 key->yuvtex_swap_mask |= 1 << i;
272          }
273
274          key->tex_swizzles[i] = t->_Swizzle;
275       }
276       else {
277          key->tex_swizzles[i] = SWIZZLE_NOOP;
278       }
279    }
280
281    /* Shadow */
282    key->shadowtex_mask = fp->program.Base.ShadowSamplers;
283
284    /* _NEW_BUFFERS */
285    /*
286     * Include the draw buffer origin and height so that we can calculate
287     * fragment position values relative to the bottom left of the drawable,
288     * from the incoming screen origin relative position we get as part of our
289     * payload.
290     *
291     * We could avoid recompiling by including this as a constant referenced by
292     * our program, but if we were to do that it would also be nice to handle
293     * getting that constant updated at batchbuffer submit time (when we
294     * hold the lock and know where the buffer really is) rather than at emit
295     * time when we don't hold the lock and are just guessing.  We could also
296     * just avoid using this as key data if the program doesn't use
297     * fragment.position.
298     *
299     * This pretty much becomes moot with DRI2 and redirected buffers anyway,
300     * as our origins will always be zero then.
301     */
302    if (brw->intel.driDrawable != NULL) {
303       key->origin_x = brw->intel.driDrawable->x;
304       key->origin_y = brw->intel.driDrawable->y;
305       key->drawable_height = brw->intel.driDrawable->h;
306    }
307
308    /* The unique fragment program ID */
309    key->program_string_id = fp->id;
310 }
311
312
313 static void brw_prepare_wm_prog(struct brw_context *brw)
314 {
315    struct brw_wm_prog_key key;
316    struct brw_fragment_program *fp = (struct brw_fragment_program *)
317       brw->fragment_program;
318      
319    brw_wm_populate_key(brw, &key);
320
321    /* Make an early check for the key.
322     */
323    dri_bo_unreference(brw->wm.prog_bo);
324    brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG,
325                                       &key, sizeof(key),
326                                       NULL, 0,
327                                       &brw->wm.prog_data);
328    if (brw->wm.prog_bo == NULL)
329       do_wm_prog(brw, fp, &key);
330 }
331
332
333 const struct brw_tracked_state brw_wm_prog = {
334    .dirty = {
335       .mesa  = (_NEW_COLOR |
336                 _NEW_DEPTH |
337                 _NEW_STENCIL |
338                 _NEW_POLYGON |
339                 _NEW_LINE |
340                 _NEW_LIGHT |
341                 _NEW_BUFFERS |
342                 _NEW_TEXTURE),
343       .brw   = (BRW_NEW_FRAGMENT_PROGRAM |
344                 BRW_NEW_WM_INPUT_DIMENSIONS |
345                 BRW_NEW_REDUCED_PRIMITIVE),
346       .cache = 0
347    },
348    .prepare = brw_prepare_wm_prog
349 };
350