1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**************************************************************************
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sub license, and/or sell copies of the Software, and to
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial portions
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the Software.
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org **************************************************************************/
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* This file contains the vertex shader tranformations for SW TCL needed
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to overcome the limitations of the r300 rasterizer.
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Transformations:
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1) If the secondary color output is present, the primary color must be
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    present too.
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2) If any back-face color output is present, there must be all 4 color
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    outputs and missing ones must be inserted.
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 3) Insert a trailing texcoord output containing a copy of POS, for WPOS.
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * I know this code is cumbersome, but I don't know of any nicer way
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of transforming TGSI shaders. ~ M.
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "r300_vs.h"
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdio.h>
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_transform.h"
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_dump.h"
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "draw/draw_context.h"
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct vs_transform_context {
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct tgsi_transform_context base;
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    boolean color_used[2];
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    boolean bcolor_used[2];
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Index of the pos output, typically 0. */
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned pos_output;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Index of the pos temp where all writes of pos are redirected to. */
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned pos_temp;
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* The index of the last generic output, after which we insert a new
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org     * output for WPOS. */
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    int last_generic;
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned num_outputs;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Used to shift output decl. indices when inserting new ones. */
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned decl_shift;
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Used to remap writes to output decls if their indices changed. */
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned out_remap[32];
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* First instruction processed? */
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    boolean first_instruction;
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* End instruction processed? */
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    boolean end_instruction;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    boolean temp_used[1024];
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void emit_temp(struct tgsi_transform_context *ctx, unsigned reg)
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct tgsi_full_declaration decl;
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl = tgsi_default_full_declaration();
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Declaration.File = TGSI_FILE_TEMPORARY;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Range.First = decl.Range.Last = reg;
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ctx->emit_declaration(ctx, &decl);
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void emit_output(struct tgsi_transform_context *ctx,
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        unsigned name, unsigned index, unsigned interp,
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        unsigned reg)
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx;
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct tgsi_full_declaration decl;
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl = tgsi_default_full_declaration();
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Declaration.File = TGSI_FILE_OUTPUT;
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Declaration.Interpolate = 1;
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Declaration.Semantic = TRUE;
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Semantic.Name = name;
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Semantic.Index = index;
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Range.First = decl.Range.Last = reg;
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    decl.Interp.Interpolate = interp;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ctx->emit_declaration(ctx, &decl);
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ++vsctx->num_outputs;
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void insert_output_before(struct tgsi_transform_context *ctx,
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 struct tgsi_full_declaration *before,
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 unsigned name, unsigned index, unsigned interp)
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx;
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned i;
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Make a place for the new output. */
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for (i = before->Range.First; i < Elements(vsctx->out_remap); i++) {
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ++vsctx->out_remap[i];
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Insert the new output. */
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    emit_output(ctx, name, index, interp,
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                before->Range.First + vsctx->decl_shift);
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ++vsctx->decl_shift;
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void insert_output_after(struct tgsi_transform_context *ctx,
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                struct tgsi_full_declaration *after,
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                unsigned name, unsigned index, unsigned interp)
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx;
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned i;
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Make a place for the new output. */
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for (i = after->Range.First+1; i < Elements(vsctx->out_remap); i++) {
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ++vsctx->out_remap[i];
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Insert the new output. */
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    emit_output(ctx, name, index, interp,
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                after->Range.First + 1);
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ++vsctx->decl_shift;
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void transform_decl(struct tgsi_transform_context *ctx,
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           struct tgsi_full_declaration *decl)
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx;
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned i;
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (decl->Declaration.File == TGSI_FILE_OUTPUT) {
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        switch (decl->Semantic.Name) {
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            case TGSI_SEMANTIC_POSITION:
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                vsctx->pos_output = decl->Range.First;
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break;
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            case TGSI_SEMANTIC_COLOR:
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                assert(decl->Semantic.Index < 2);
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                /* We must rasterize the first color if the second one is
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 * used, otherwise the rasterizer doesn't do the color
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 * selection correctly. Declare it, but don't write to it. */
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if (decl->Semantic.Index == 1 && !vsctx->color_used[0]) {
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 0,
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         TGSI_INTERPOLATE_LINEAR);
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    vsctx->color_used[0] = TRUE;
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                }
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break;
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            case TGSI_SEMANTIC_BCOLOR:
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                assert(decl->Semantic.Index < 2);
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                /* We must rasterize all 4 colors if back-face colors are
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 * used, otherwise the rasterizer doesn't do the color
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 * selection correctly. Declare it, but don't write to it. */
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if (!vsctx->color_used[0]) {
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 0,
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         TGSI_INTERPOLATE_LINEAR);
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    vsctx->color_used[0] = TRUE;
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                }
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if (!vsctx->color_used[1]) {
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 1,
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         TGSI_INTERPOLATE_LINEAR);
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    vsctx->color_used[1] = TRUE;
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                }
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if (decl->Semantic.Index == 1 && !vsctx->bcolor_used[0]) {
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    insert_output_before(ctx, decl, TGSI_SEMANTIC_BCOLOR, 0,
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         TGSI_INTERPOLATE_LINEAR);
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    vsctx->bcolor_used[0] = TRUE;
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                }
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break;
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            case TGSI_SEMANTIC_GENERIC:
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                vsctx->last_generic = MAX2(vsctx->last_generic, decl->Semantic.Index);
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break;
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        }
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* Since we're inserting new outputs in between, the following outputs
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         * should be moved to the right so that they don't overlap with
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         * the newly added ones. */
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        decl->Range.First += vsctx->decl_shift;
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        decl->Range.Last += vsctx->decl_shift;
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ++vsctx->num_outputs;
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for (i = decl->Range.First; i <= decl->Range.Last; i++) {
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           vsctx->temp_used[i] = TRUE;
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        }
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ctx->emit_declaration(ctx, decl);
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Insert BCOLOR1 if needed. */
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        decl->Semantic.Name == TGSI_SEMANTIC_BCOLOR &&
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        !vsctx->bcolor_used[1]) {
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        insert_output_after(ctx, decl, TGSI_SEMANTIC_BCOLOR, 1,
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            TGSI_INTERPOLATE_LINEAR);
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void transform_inst(struct tgsi_transform_context *ctx,
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           struct tgsi_full_instruction *inst)
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct vs_transform_context *vsctx = (struct vs_transform_context *) ctx;
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct tgsi_full_instruction new_inst;
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned i;
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (!vsctx->first_instruction) {
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        vsctx->first_instruction = TRUE;
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* Insert the generic output for WPOS. */
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        emit_output(ctx, TGSI_SEMANTIC_GENERIC, vsctx->last_generic + 1,
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    TGSI_INTERPOLATE_PERSPECTIVE, vsctx->num_outputs);
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* Find a free temp for POSITION. */
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for (i = 0; i < Elements(vsctx->temp_used); i++) {
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (!vsctx->temp_used[i]) {
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                emit_temp(ctx, i);
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                vsctx->pos_temp = i;
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break;
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        }
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* MOV OUT[pos_output], TEMP[pos_temp]; */
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst = tgsi_default_full_instruction();
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Instruction.NumDstRegs = 1;
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT;
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Dst[0].Register.Index = vsctx->pos_output;
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW;
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Instruction.NumSrcRegs = 1;
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Src[0].Register.Index = vsctx->pos_temp;
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ctx->emit_instruction(ctx, &new_inst);
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* MOV OUT[n-1], TEMP[pos_temp]; */
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst = tgsi_default_full_instruction();
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Instruction.NumDstRegs = 1;
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT;
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Dst[0].Register.Index = vsctx->num_outputs - 1;
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW;
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Instruction.NumSrcRegs = 1;
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        new_inst.Src[0].Register.Index = vsctx->pos_temp;
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ctx->emit_instruction(ctx, &new_inst);
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        vsctx->end_instruction = TRUE;
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else {
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* Not an END instruction. */
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* Fix writes to outputs. */
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            struct tgsi_full_dst_register *dst = &inst->Dst[i];
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (dst->Register.File == TGSI_FILE_OUTPUT) {
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if (dst->Register.Index == vsctx->pos_output) {
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    /* Replace writes to OUT[pos_output] with TEMP[pos_temp]. */
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    dst->Register.File = TGSI_FILE_TEMPORARY;
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    dst->Register.Index = vsctx->pos_temp;
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                } else {
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    /* Not a position, good...
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     * Since we were changing the indices of output decls,
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     * we must redirect writes into them too. */
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    dst->Register.Index = vsctx->out_remap[dst->Register.Index];
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                }
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        }
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* Inserting 2 instructions before the END opcode moves all following
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         * labels by 2. Subroutines are always after the END opcode so
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         * they're always moved. */
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if (inst->Instruction.Opcode == TGSI_OPCODE_CAL) {
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            inst->Label.Label += 2;
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        }
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        /* The labels of the following opcodes are moved only after
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         * the END opcode. */
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if (vsctx->end_instruction &&
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP ||
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             inst->Instruction.Opcode == TGSI_OPCODE_ENDLOOP)) {
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            inst->Label.Label += 2;
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        }
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ctx->emit_instruction(ctx, inst);
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid r300_draw_init_vertex_shader(struct r300_context *r300,
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  struct r300_vertex_shader *vs)
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct draw_context *draw = r300->draw;
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct pipe_shader_state new_vs;
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct tgsi_shader_info info;
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    struct vs_transform_context transform;
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const uint newLen = tgsi_num_tokens(vs->state.tokens) + 100 /* XXX */;
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned i;
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    tgsi_scan_shader(vs->state.tokens, &info);
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    new_vs.tokens = tgsi_alloc_tokens(newLen);
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (new_vs.tokens == NULL)
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return;
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    memset(&transform, 0, sizeof(transform));
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for (i = 0; i < Elements(transform.out_remap); i++) {
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        transform.out_remap[i] = i;
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    transform.last_generic = -1;
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    transform.base.transform_instruction = transform_inst;
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    transform.base.transform_declaration = transform_decl;
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for (i = 0; i < info.num_outputs; i++) {
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        unsigned index = info.output_semantic_index[i];
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        switch (info.output_semantic_name[i]) {
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            case TGSI_SEMANTIC_COLOR:
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                assert(index < 2);
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                transform.color_used[index] = TRUE;
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break;
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            case TGSI_SEMANTIC_BCOLOR:
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                assert(index < 2);
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                transform.bcolor_used[index] = TRUE;
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break;
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        }
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    tgsi_transform_shader(vs->state.tokens,
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          (struct tgsi_token*)new_vs.tokens,
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          newLen, &transform.base);
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if 0
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    printf("----------------------------------------------\norig shader:\n");
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    tgsi_dump(vs->state.tokens, 0);
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    printf("----------------------------------------------\nnew shader:\n");
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    tgsi_dump(new_vs.tokens, 0);
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    printf("----------------------------------------------\n");
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Free old tokens. */
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    FREE((void*)vs->state.tokens);
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    vs->draw_vs = draw_create_vertex_shader(draw, &new_vs);
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Instead of duplicating and freeing the tokens, copy the pointer directly. */
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    vs->state.tokens = new_vs.tokens;
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Init the VS output table for the rasterizer. */
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    r300_init_vs_outputs(r300, vs);
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    /* Make the last generic be WPOS. */
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    vs->outputs.wpos = vs->outputs.generic[transform.last_generic + 1];
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    vs->outputs.generic[transform.last_generic + 1] = ATTR_UNUSED;
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
378