190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák/**************************************************************************
290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák *
390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * Copyright 2009 Marek Olšák <maraeo@gmail.com>
490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák *
590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * Permission is hereby granted, free of charge, to any person obtaining a
690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * copy of this software and associated documentation files (the
790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * "Software"), to deal in the Software without restriction, including
890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * without limitation the rights to use, copy, modify, merge, publish,
990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * distribute, sub license, and/or sell copies of the Software, and to
1090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * permit persons to whom the Software is furnished to do so, subject to
1190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * the following conditions:
1290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák *
1390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * The above copyright notice and this permission notice (including the
1490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * next paragraph) shall be included in all copies or substantial portions
1590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * of the Software.
1690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák *
1790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák *
2590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák **************************************************************************/
2690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
2790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák/* This file contains the vertex shader tranformations for SW TCL needed
2890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * to overcome the limitations of the r300 rasterizer.
2990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák *
3090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * Transformations:
3190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * 1) If the secondary color output is present, the primary color must be
3275f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák *    present too.
3390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * 2) If any back-face color output is present, there must be all 4 color
3490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák *    outputs and missing ones must be inserted.
3590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * 3) Insert a trailing texcoord output containing a copy of POS, for WPOS.
3690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák *
3790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * I know this code is cumbersome, but I don't know of any nicer way
3890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák * of transforming TGSI shaders. ~ M.
3990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák */
4090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
4190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák#include "r300_vs.h"
4290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
4390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák#include <stdio.h>
4490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
4590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák#include "tgsi/tgsi_transform.h"
4690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák#include "tgsi/tgsi_dump.h"
4790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
4890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák#include "draw/draw_context.h"
4990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
5090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšákstruct vs_transform_context {
5190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct tgsi_transform_context base;
5290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
5390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    boolean color_used[2];
5490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    boolean bcolor_used[2];
5590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
5690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Index of the pos output, typically 0. */
5790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned pos_output;
5890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Index of the pos temp where all writes of pos are redirected to. */
5990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned pos_temp;
6090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* The index of the last generic output, after which we insert a new
6190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák     * output for WPOS. */
6290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    int last_generic;
6390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
6490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned num_outputs;
6590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Used to shift output decl. indices when inserting new ones. */
6690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned decl_shift;
6790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Used to remap writes to output decls if their indices changed. */
6890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned out_remap[32];
6990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
7090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* First instruction processed? */
7190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    boolean first_instruction;
7290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* End instruction processed? */
7390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    boolean end_instruction;
7475f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák
7575f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    boolean temp_used[1024];
7690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák};
7790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
7890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšákstatic void emit_temp(struct tgsi_transform_context *ctx, unsigned reg)
7990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák{
8090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct tgsi_full_declaration decl;
8190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
8290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl = tgsi_default_full_declaration();
8390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl.Declaration.File = TGSI_FILE_TEMPORARY;
8490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl.Range.First = decl.Range.Last = reg;
8590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    ctx->emit_declaration(ctx, &decl);
8690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák}
8790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
8890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšákstatic void emit_output(struct tgsi_transform_context *ctx,
8990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                        unsigned name, unsigned index, unsigned interp,
9090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                        unsigned reg)
9190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák{
9290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx;
9390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct tgsi_full_declaration decl;
9490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
9590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl = tgsi_default_full_declaration();
9690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl.Declaration.File = TGSI_FILE_OUTPUT;
971279923d72942ee201fcc6ad40d552143f651f03Francisco Jerez    decl.Declaration.Interpolate = 1;
9890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl.Declaration.Semantic = TRUE;
9990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl.Semantic.Name = name;
10090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl.Semantic.Index = index;
10190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    decl.Range.First = decl.Range.Last = reg;
1021279923d72942ee201fcc6ad40d552143f651f03Francisco Jerez    decl.Interp.Interpolate = interp;
10390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    ctx->emit_declaration(ctx, &decl);
10490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    ++vsctx->num_outputs;
10590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák}
10690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
10775f8990547903f7dde5d98319cc813f94a15aa78Marek Olšákstatic void insert_output_before(struct tgsi_transform_context *ctx,
10875f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                                 struct tgsi_full_declaration *before,
10975f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                                 unsigned name, unsigned index, unsigned interp)
11090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák{
11190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx;
11290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned i;
11390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
11490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Make a place for the new output. */
11590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    for (i = before->Range.First; i < Elements(vsctx->out_remap); i++) {
11690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        ++vsctx->out_remap[i];
11790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    }
11890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
11990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Insert the new output. */
12075f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    emit_output(ctx, name, index, interp,
12175f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                before->Range.First + vsctx->decl_shift);
12290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
12390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    ++vsctx->decl_shift;
12490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák}
12590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
12675f8990547903f7dde5d98319cc813f94a15aa78Marek Olšákstatic void insert_output_after(struct tgsi_transform_context *ctx,
12775f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                                struct tgsi_full_declaration *after,
12875f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                                unsigned name, unsigned index, unsigned interp)
12990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák{
13090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx;
13175f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    unsigned i;
13290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
13375f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    /* Make a place for the new output. */
13475f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    for (i = after->Range.First+1; i < Elements(vsctx->out_remap); i++) {
13575f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák        ++vsctx->out_remap[i];
13690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    }
13775f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák
13875f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    /* Insert the new output. */
13975f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    emit_output(ctx, name, index, interp,
14075f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                after->Range.First + 1);
14175f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák
14275f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    ++vsctx->decl_shift;
14390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák}
14490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
14590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšákstatic void transform_decl(struct tgsi_transform_context *ctx,
14690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                           struct tgsi_full_declaration *decl)
14790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák{
14890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx;
14990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned i;
15090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
15190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    if (decl->Declaration.File == TGSI_FILE_OUTPUT) {
15290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        switch (decl->Semantic.Name) {
15390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            case TGSI_SEMANTIC_POSITION:
15490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                vsctx->pos_output = decl->Range.First;
15590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                break;
15690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
15790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            case TGSI_SEMANTIC_COLOR:
15890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                assert(decl->Semantic.Index < 2);
15990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
16090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                /* We must rasterize the first color if the second one is
16190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                 * used, otherwise the rasterizer doesn't do the color
16290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                 * selection correctly. Declare it, but don't write to it. */
16390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                if (decl->Semantic.Index == 1 && !vsctx->color_used[0]) {
16475f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                    insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 0,
16575f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                                         TGSI_INTERPOLATE_LINEAR);
16690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    vsctx->color_used[0] = TRUE;
16790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                }
16890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                break;
16990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
17090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            case TGSI_SEMANTIC_BCOLOR:
17190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                assert(decl->Semantic.Index < 2);
17290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
17390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                /* We must rasterize all 4 colors if back-face colors are
17490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                 * used, otherwise the rasterizer doesn't do the color
17590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                 * selection correctly. Declare it, but don't write to it. */
17690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                if (!vsctx->color_used[0]) {
17775f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                    insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 0,
17875f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                                         TGSI_INTERPOLATE_LINEAR);
17990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    vsctx->color_used[0] = TRUE;
18090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                }
18190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                if (!vsctx->color_used[1]) {
18275f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                    insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 1,
18375f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                                         TGSI_INTERPOLATE_LINEAR);
18490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    vsctx->color_used[1] = TRUE;
18590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                }
18690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                if (decl->Semantic.Index == 1 && !vsctx->bcolor_used[0]) {
18775f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                    insert_output_before(ctx, decl, TGSI_SEMANTIC_BCOLOR, 0,
18875f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                                         TGSI_INTERPOLATE_LINEAR);
18975d0e95a3ad188ae1c4cc38a73241c6b227c0733Marek Olšák                    vsctx->bcolor_used[0] = TRUE;
19090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                }
19190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                break;
19290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
19390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            case TGSI_SEMANTIC_GENERIC:
19490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                vsctx->last_generic = MAX2(vsctx->last_generic, decl->Semantic.Index);
19590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                break;
19690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        }
19790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
19890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* Since we're inserting new outputs in between, the following outputs
19990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák         * should be moved to the right so that they don't overlap with
20090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák         * the newly added ones. */
20190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        decl->Range.First += vsctx->decl_shift;
20290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        decl->Range.Last += vsctx->decl_shift;
20390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
20490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        ++vsctx->num_outputs;
20590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    } else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
20690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        for (i = decl->Range.First; i <= decl->Range.Last; i++) {
20790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák           vsctx->temp_used[i] = TRUE;
20890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        }
20990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    }
21090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
21190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    ctx->emit_declaration(ctx, decl);
21275f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák
21375f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    /* Insert BCOLOR1 if needed. */
21475f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
21575f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák        decl->Semantic.Name == TGSI_SEMANTIC_BCOLOR &&
21675f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák        !vsctx->bcolor_used[1]) {
21775f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák        insert_output_after(ctx, decl, TGSI_SEMANTIC_BCOLOR, 1,
21875f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                            TGSI_INTERPOLATE_LINEAR);
21975f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    }
22090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák}
22190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
22290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšákstatic void transform_inst(struct tgsi_transform_context *ctx,
22390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                           struct tgsi_full_instruction *inst)
22490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák{
22590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct vs_transform_context *vsctx = (struct vs_transform_context *) ctx;
22690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct tgsi_full_instruction new_inst;
22790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned i;
22890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
22990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    if (!vsctx->first_instruction) {
23090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        vsctx->first_instruction = TRUE;
23190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
23290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* Insert the generic output for WPOS. */
23390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        emit_output(ctx, TGSI_SEMANTIC_GENERIC, vsctx->last_generic + 1,
23490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    TGSI_INTERPOLATE_PERSPECTIVE, vsctx->num_outputs);
23590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
23690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* Find a free temp for POSITION. */
23790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        for (i = 0; i < Elements(vsctx->temp_used); i++) {
23890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            if (!vsctx->temp_used[i]) {
23990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                emit_temp(ctx, i);
24090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                vsctx->pos_temp = i;
24190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                break;
24290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            }
24390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        }
24490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    }
24590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
24690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
24790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* MOV OUT[pos_output], TEMP[pos_temp]; */
24890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst = tgsi_default_full_instruction();
24990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
25090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Instruction.NumDstRegs = 1;
25190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT;
25290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Dst[0].Register.Index = vsctx->pos_output;
25390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW;
25490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Instruction.NumSrcRegs = 1;
25590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
25690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Src[0].Register.Index = vsctx->pos_temp;
25790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        ctx->emit_instruction(ctx, &new_inst);
25890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
25990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* MOV OUT[n-1], TEMP[pos_temp]; */
26090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst = tgsi_default_full_instruction();
26190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Instruction.Opcode = TGSI_OPCODE_MOV;
26290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Instruction.NumDstRegs = 1;
26390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT;
26490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Dst[0].Register.Index = vsctx->num_outputs - 1;
26590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW;
26690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Instruction.NumSrcRegs = 1;
26790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
26890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        new_inst.Src[0].Register.Index = vsctx->pos_temp;
26990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        ctx->emit_instruction(ctx, &new_inst);
27090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
27190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        vsctx->end_instruction = TRUE;
27290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    } else {
27390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* Not an END instruction. */
27490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* Fix writes to outputs. */
27590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
27690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            struct tgsi_full_dst_register *dst = &inst->Dst[i];
27790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            if (dst->Register.File == TGSI_FILE_OUTPUT) {
27890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                if (dst->Register.Index == vsctx->pos_output) {
27990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    /* Replace writes to OUT[pos_output] with TEMP[pos_temp]. */
28090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    dst->Register.File = TGSI_FILE_TEMPORARY;
28190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    dst->Register.Index = vsctx->pos_temp;
28290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                } else {
28390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    /* Not a position, good...
28490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                     * Since we were changing the indices of output decls,
28590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                     * we must redirect writes into them too. */
28690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                    dst->Register.Index = vsctx->out_remap[dst->Register.Index];
28790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                }
28890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            }
28990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        }
29090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
29190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* Inserting 2 instructions before the END opcode moves all following
29290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák         * labels by 2. Subroutines are always after the END opcode so
29390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák         * they're always moved. */
29490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        if (inst->Instruction.Opcode == TGSI_OPCODE_CAL) {
29590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            inst->Label.Label += 2;
29690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        }
29790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        /* The labels of the following opcodes are moved only after
29890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák         * the END opcode. */
29990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        if (vsctx->end_instruction &&
30090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
30190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák             inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
30290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák             inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP ||
30390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák             inst->Instruction.Opcode == TGSI_OPCODE_ENDLOOP)) {
30490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák            inst->Label.Label += 2;
30590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        }
30690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    }
30790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
30890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    ctx->emit_instruction(ctx, inst);
30990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák}
31090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
3115ce0598a034179eaacff96f39eaebf0ba0f30d4cMarek Olšákvoid r300_draw_init_vertex_shader(struct r300_context *r300,
31290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                                  struct r300_vertex_shader *vs)
31390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák{
3145ce0598a034179eaacff96f39eaebf0ba0f30d4cMarek Olšák    struct draw_context *draw = r300->draw;
31590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct pipe_shader_state new_vs;
31675f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    struct tgsi_shader_info info;
31790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    struct vs_transform_context transform;
31890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    const uint newLen = tgsi_num_tokens(vs->state.tokens) + 100 /* XXX */;
31990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    unsigned i;
32090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
32175f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    tgsi_scan_shader(vs->state.tokens, &info);
32275f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák
32390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    new_vs.tokens = tgsi_alloc_tokens(newLen);
32490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    if (new_vs.tokens == NULL)
32590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        return;
32690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
32790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    memset(&transform, 0, sizeof(transform));
32890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    for (i = 0; i < Elements(transform.out_remap); i++) {
32990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák        transform.out_remap[i] = i;
33090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    }
33190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    transform.last_generic = -1;
33290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    transform.base.transform_instruction = transform_inst;
33390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    transform.base.transform_declaration = transform_decl;
33490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
33575f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    for (i = 0; i < info.num_outputs; i++) {
33675f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák        unsigned index = info.output_semantic_index[i];
33775f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák
33875f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák        switch (info.output_semantic_name[i]) {
33975f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák            case TGSI_SEMANTIC_COLOR:
34075f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                assert(index < 2);
34175f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                transform.color_used[index] = TRUE;
34275f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                break;
34375f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák
34475f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák            case TGSI_SEMANTIC_BCOLOR:
34575f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                assert(index < 2);
34675f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                transform.bcolor_used[index] = TRUE;
34775f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák                break;
34875f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák        }
34975f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák    }
35075f8990547903f7dde5d98319cc813f94a15aa78Marek Olšák
35190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    tgsi_transform_shader(vs->state.tokens,
35290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                          (struct tgsi_token*)new_vs.tokens,
35390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák                          newLen, &transform.base);
35490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
35590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák#if 0
35690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    printf("----------------------------------------------\norig shader:\n");
35790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    tgsi_dump(vs->state.tokens, 0);
35890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    printf("----------------------------------------------\nnew shader:\n");
35990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    tgsi_dump(new_vs.tokens, 0);
36090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    printf("----------------------------------------------\n");
36190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák#endif
36290e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
36390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Free old tokens. */
36490e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    FREE((void*)vs->state.tokens);
36590e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
36690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    vs->draw_vs = draw_create_vertex_shader(draw, &new_vs);
36790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
36890e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Instead of duplicating and freeing the tokens, copy the pointer directly. */
36990e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    vs->state.tokens = new_vs.tokens;
37090e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
37190e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    /* Init the VS output table for the rasterizer. */
3725ce0598a034179eaacff96f39eaebf0ba0f30d4cMarek Olšák    r300_init_vs_outputs(r300, vs);
37390e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák
3743262554bb375230a39e155ad712740bdcd657d4cMarek Olšák    /* Make the last generic be WPOS. */
3753262554bb375230a39e155ad712740bdcd657d4cMarek Olšák    vs->outputs.wpos = vs->outputs.generic[transform.last_generic + 1];
37690e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák    vs->outputs.generic[transform.last_generic + 1] = ATTR_UNUSED;
37790e5a37d128efaca9e89434ab103826ee82cb911Marek Olšák}
378