1 /*
2  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3  Intel funded Tungsten Graphics 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 <keithw@vmware.com>
30   */
31 
32 #include "main/macros.h"
33 #include "main/enums.h"
34 #include "main/transformfeedback.h"
35 
36 #include "brw_batch.h"
37 
38 #include "brw_defines.h"
39 #include "brw_context.h"
40 #include "brw_util.h"
41 #include "brw_state.h"
42 #include "brw_ff_gs.h"
43 #include "util/ralloc.h"
44 
45 static void
compile_ff_gs_prog(struct brw_context * brw,struct brw_ff_gs_prog_key * key)46 compile_ff_gs_prog(struct brw_context *brw,
47 		   struct brw_ff_gs_prog_key *key)
48 {
49    const GLuint *program;
50    void *mem_ctx;
51    GLuint program_size;
52 
53    mem_ctx = ralloc_context(NULL);
54 
55    struct brw_ff_gs_prog_data prog_data;
56    program = brw_compile_ff_gs_prog(brw->screen->compiler, mem_ctx, key,
57                                     &prog_data,
58                                     &brw_vue_prog_data(brw->vs.base.prog_data)->vue_map,
59                                     &program_size);
60 
61    brw_upload_cache(&brw->cache, BRW_CACHE_FF_GS_PROG,
62                     key, sizeof(*key),
63                     program, program_size,
64                     &prog_data, sizeof(prog_data),
65                     &brw->ff_gs.prog_offset, &brw->ff_gs.prog_data);
66    ralloc_free(mem_ctx);
67 }
68 
69 static bool
brw_ff_gs_state_dirty(const struct brw_context * brw)70 brw_ff_gs_state_dirty(const struct brw_context *brw)
71 {
72    return brw_state_dirty(brw,
73                           _NEW_LIGHT,
74                           BRW_NEW_PRIMITIVE |
75                           BRW_NEW_TRANSFORM_FEEDBACK |
76                           BRW_NEW_VS_PROG_DATA);
77 }
78 
79 static void
brw_ff_gs_populate_key(struct brw_context * brw,struct brw_ff_gs_prog_key * key)80 brw_ff_gs_populate_key(struct brw_context *brw,
81                        struct brw_ff_gs_prog_key *key)
82 {
83    const struct intel_device_info *devinfo = &brw->screen->devinfo;
84    static const unsigned swizzle_for_offset[4] = {
85       BRW_SWIZZLE4(0, 1, 2, 3),
86       BRW_SWIZZLE4(1, 2, 3, 3),
87       BRW_SWIZZLE4(2, 3, 3, 3),
88       BRW_SWIZZLE4(3, 3, 3, 3)
89    };
90 
91    struct gl_context *ctx = &brw->ctx;
92 
93    assert(devinfo->ver < 7);
94 
95    memset(key, 0, sizeof(*key));
96 
97    /* BRW_NEW_VS_PROG_DATA (part of VUE map) */
98    key->attrs = brw_vue_prog_data(brw->vs.base.prog_data)->vue_map.slots_valid;
99 
100    /* BRW_NEW_PRIMITIVE */
101    key->primitive = brw->primitive;
102 
103    /* _NEW_LIGHT */
104    key->pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
105    if (key->primitive == _3DPRIM_QUADLIST && ctx->Light.ShadeModel != GL_FLAT) {
106       /* Provide consistent primitive order with brw_set_prim's
107        * optimization of single quads to trifans.
108        */
109       key->pv_first = true;
110    }
111 
112    if (devinfo->ver == 6) {
113       /* On Gfx6, GS is used for transform feedback. */
114       /* BRW_NEW_TRANSFORM_FEEDBACK */
115       if (_mesa_is_xfb_active_and_unpaused(ctx)) {
116          const struct gl_program *prog =
117             ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
118          const struct gl_transform_feedback_info *linked_xfb_info =
119             prog->sh.LinkedTransformFeedback;
120          int i;
121 
122          /* Make sure that the VUE slots won't overflow the unsigned chars in
123           * key->transform_feedback_bindings[].
124           */
125          STATIC_ASSERT(BRW_VARYING_SLOT_COUNT <= 256);
126 
127          /* Make sure that we don't need more binding table entries than we've
128           * set aside for use in transform feedback.  (We shouldn't, since we
129           * set aside enough binding table entries to have one per component).
130           */
131          assert(linked_xfb_info->NumOutputs <= BRW_MAX_SOL_BINDINGS);
132 
133          key->need_gs_prog = true;
134          key->num_transform_feedback_bindings = linked_xfb_info->NumOutputs;
135          for (i = 0; i < key->num_transform_feedback_bindings; ++i) {
136             key->transform_feedback_bindings[i] =
137                linked_xfb_info->Outputs[i].OutputRegister;
138             key->transform_feedback_swizzles[i] =
139                swizzle_for_offset[linked_xfb_info->Outputs[i].ComponentOffset];
140          }
141       }
142    } else {
143       /* Pre-gfx6, GS is used to transform QUADLIST, QUADSTRIP, and LINELOOP
144        * into simpler primitives.
145        */
146       key->need_gs_prog = (brw->primitive == _3DPRIM_QUADLIST ||
147                            brw->primitive == _3DPRIM_QUADSTRIP ||
148                            brw->primitive == _3DPRIM_LINELOOP);
149    }
150 }
151 
152 /* Calculate interpolants for triangle and line rasterization.
153  */
154 void
brw_upload_ff_gs_prog(struct brw_context * brw)155 brw_upload_ff_gs_prog(struct brw_context *brw)
156 {
157    struct brw_ff_gs_prog_key key;
158 
159    if (!brw_ff_gs_state_dirty(brw))
160       return;
161 
162    /* Populate the key:
163     */
164    brw_ff_gs_populate_key(brw, &key);
165 
166    if (brw->ff_gs.prog_active != key.need_gs_prog) {
167       brw->ctx.NewDriverState |= BRW_NEW_FF_GS_PROG_DATA;
168       brw->ff_gs.prog_active = key.need_gs_prog;
169    }
170 
171    if (brw->ff_gs.prog_active) {
172       if (!brw_search_cache(&brw->cache, BRW_CACHE_FF_GS_PROG, &key,
173                             sizeof(key), &brw->ff_gs.prog_offset,
174                             &brw->ff_gs.prog_data, true)) {
175          compile_ff_gs_prog(brw, &key);
176       }
177    }
178 }
179