1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3bf215546Sopenharmony_ci * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "draw/draw_context.h"
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "util/u_math.h"
27bf215546Sopenharmony_ci#include "util/u_memory.h"
28bf215546Sopenharmony_ci#include "util/u_pack_color.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "r300_context.h"
31bf215546Sopenharmony_ci#include "r300_fs.h"
32bf215546Sopenharmony_ci#include "r300_screen.h"
33bf215546Sopenharmony_ci#include "r300_shader_semantics.h"
34bf215546Sopenharmony_ci#include "r300_state_inlines.h"
35bf215546Sopenharmony_ci#include "r300_texture.h"
36bf215546Sopenharmony_ci#include "r300_vs.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci/* r300_state_derived: Various bits of state which are dependent upon
39bf215546Sopenharmony_ci * currently bound CSO data. */
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_cienum r300_rs_swizzle {
42bf215546Sopenharmony_ci    SWIZ_XYZW = 0,
43bf215546Sopenharmony_ci    SWIZ_X001,
44bf215546Sopenharmony_ci    SWIZ_XY01,
45bf215546Sopenharmony_ci    SWIZ_0001,
46bf215546Sopenharmony_ci};
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_cienum r300_rs_col_write_type {
49bf215546Sopenharmony_ci    WRITE_COLOR = 0,
50bf215546Sopenharmony_ci    WRITE_FACE
51bf215546Sopenharmony_ci};
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistatic void r300_draw_emit_attrib(struct r300_context* r300,
54bf215546Sopenharmony_ci                                  enum attrib_emit emit,
55bf215546Sopenharmony_ci                                  int index)
56bf215546Sopenharmony_ci{
57bf215546Sopenharmony_ci    struct r300_vertex_shader_code* vs = r300_vs(r300)->shader;
58bf215546Sopenharmony_ci    struct tgsi_shader_info* info = &vs->info;
59bf215546Sopenharmony_ci    int output;
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci    output = draw_find_shader_output(r300->draw,
62bf215546Sopenharmony_ci                                     info->output_semantic_name[index],
63bf215546Sopenharmony_ci                                     info->output_semantic_index[index]);
64bf215546Sopenharmony_ci    draw_emit_vertex_attr(&r300->vertex_info, emit, output);
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_cistatic void r300_draw_emit_all_attribs(struct r300_context* r300)
68bf215546Sopenharmony_ci{
69bf215546Sopenharmony_ci    struct r300_vertex_shader_code* vs = r300_vs(r300)->shader;
70bf215546Sopenharmony_ci    struct r300_shader_semantics* vs_outputs = &vs->outputs;
71bf215546Sopenharmony_ci    int i, gen_count;
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci    /* Position. */
74bf215546Sopenharmony_ci    if (vs_outputs->pos != ATTR_UNUSED) {
75bf215546Sopenharmony_ci        r300_draw_emit_attrib(r300, EMIT_4F, vs_outputs->pos);
76bf215546Sopenharmony_ci    } else {
77bf215546Sopenharmony_ci        assert(0);
78bf215546Sopenharmony_ci    }
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci    /* Point size. */
81bf215546Sopenharmony_ci    if (vs_outputs->psize != ATTR_UNUSED) {
82bf215546Sopenharmony_ci        r300_draw_emit_attrib(r300, EMIT_1F_PSIZE, vs_outputs->psize);
83bf215546Sopenharmony_ci    }
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci    /* Colors. */
86bf215546Sopenharmony_ci    for (i = 0; i < ATTR_COLOR_COUNT; i++) {
87bf215546Sopenharmony_ci        if (vs_outputs->color[i] != ATTR_UNUSED) {
88bf215546Sopenharmony_ci            r300_draw_emit_attrib(r300, EMIT_4F, vs_outputs->color[i]);
89bf215546Sopenharmony_ci        }
90bf215546Sopenharmony_ci    }
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci    /* Back-face colors. */
93bf215546Sopenharmony_ci    for (i = 0; i < ATTR_COLOR_COUNT; i++) {
94bf215546Sopenharmony_ci        if (vs_outputs->bcolor[i] != ATTR_UNUSED) {
95bf215546Sopenharmony_ci            r300_draw_emit_attrib(r300, EMIT_4F, vs_outputs->bcolor[i]);
96bf215546Sopenharmony_ci        }
97bf215546Sopenharmony_ci    }
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci    /* Texture coordinates. */
100bf215546Sopenharmony_ci    /* Only 8 generic vertex attributes can be used. If there are more,
101bf215546Sopenharmony_ci     * they won't be rasterized. */
102bf215546Sopenharmony_ci    gen_count = 0;
103bf215546Sopenharmony_ci    for (i = 0; i < ATTR_GENERIC_COUNT && gen_count < 8; i++) {
104bf215546Sopenharmony_ci        if (vs_outputs->generic[i] != ATTR_UNUSED &&
105bf215546Sopenharmony_ci            (!(r300->sprite_coord_enable & (1U << i)) || !r300->is_point)) {
106bf215546Sopenharmony_ci            r300_draw_emit_attrib(r300, EMIT_4F, vs_outputs->generic[i]);
107bf215546Sopenharmony_ci            gen_count++;
108bf215546Sopenharmony_ci        }
109bf215546Sopenharmony_ci    }
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci    /* Fog coordinates. */
112bf215546Sopenharmony_ci    if (gen_count < 8 && vs_outputs->fog != ATTR_UNUSED) {
113bf215546Sopenharmony_ci        r300_draw_emit_attrib(r300, EMIT_4F, vs_outputs->fog);
114bf215546Sopenharmony_ci        gen_count++;
115bf215546Sopenharmony_ci    }
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci    /* WPOS. */
118bf215546Sopenharmony_ci    if (r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED && gen_count < 8) {
119bf215546Sopenharmony_ci        DBG(r300, DBG_SWTCL, "draw_emit_attrib: WPOS, index: %i\n",
120bf215546Sopenharmony_ci            vs_outputs->wpos);
121bf215546Sopenharmony_ci        r300_draw_emit_attrib(r300, EMIT_4F, vs_outputs->wpos);
122bf215546Sopenharmony_ci    }
123bf215546Sopenharmony_ci}
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci/* Update the PSC tables for SW TCL, using Draw. */
126bf215546Sopenharmony_cistatic void r300_swtcl_vertex_psc(struct r300_context *r300)
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci    struct r300_vertex_stream_state *vstream = r300->vertex_stream_state.state;
129bf215546Sopenharmony_ci    struct vertex_info *vinfo = &r300->vertex_info;
130bf215546Sopenharmony_ci    uint16_t type, swizzle;
131bf215546Sopenharmony_ci    enum pipe_format format;
132bf215546Sopenharmony_ci    unsigned i, attrib_count;
133bf215546Sopenharmony_ci    int* vs_output_tab = r300->stream_loc_notcl;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci    memset(vstream, 0, sizeof(struct r300_vertex_stream_state));
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci    /* For each Draw attribute, route it to the fragment shader according
138bf215546Sopenharmony_ci     * to the vs_output_tab. */
139bf215546Sopenharmony_ci    attrib_count = vinfo->num_attribs;
140bf215546Sopenharmony_ci    DBG(r300, DBG_SWTCL, "r300: attrib count: %d\n", attrib_count);
141bf215546Sopenharmony_ci    for (i = 0; i < attrib_count; i++) {
142bf215546Sopenharmony_ci        if (vs_output_tab[i] == -1) {
143bf215546Sopenharmony_ci            assert(0);
144bf215546Sopenharmony_ci            abort();
145bf215546Sopenharmony_ci        }
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci        format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci        DBG(r300, DBG_SWTCL,
150bf215546Sopenharmony_ci            "r300: swtcl_vertex_psc [%i] <- %s\n",
151bf215546Sopenharmony_ci            vs_output_tab[i], util_format_short_name(format));
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci        /* Obtain the type of data in this attribute. */
154bf215546Sopenharmony_ci        type = r300_translate_vertex_data_type(format);
155bf215546Sopenharmony_ci        if (type == R300_INVALID_FORMAT) {
156bf215546Sopenharmony_ci            fprintf(stderr, "r300: Bad vertex format %s.\n",
157bf215546Sopenharmony_ci                    util_format_short_name(format));
158bf215546Sopenharmony_ci            assert(0);
159bf215546Sopenharmony_ci            abort();
160bf215546Sopenharmony_ci        }
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci        type |= vs_output_tab[i] << R300_DST_VEC_LOC_SHIFT;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci        /* Obtain the swizzle for this attribute. Note that the default
165bf215546Sopenharmony_ci         * swizzle in the hardware is not XYZW! */
166bf215546Sopenharmony_ci        swizzle = r300_translate_vertex_data_swizzle(format);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci        /* Add the attribute to the PSC table. */
169bf215546Sopenharmony_ci        if (i & 1) {
170bf215546Sopenharmony_ci            vstream->vap_prog_stream_cntl[i >> 1] |= type << 16;
171bf215546Sopenharmony_ci            vstream->vap_prog_stream_cntl_ext[i >> 1] |= (uint32_t)swizzle << 16;
172bf215546Sopenharmony_ci        } else {
173bf215546Sopenharmony_ci            vstream->vap_prog_stream_cntl[i >> 1] |= type;
174bf215546Sopenharmony_ci            vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle;
175bf215546Sopenharmony_ci        }
176bf215546Sopenharmony_ci    }
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci    /* Set the last vector in the PSC. */
179bf215546Sopenharmony_ci    if (i) {
180bf215546Sopenharmony_ci        i -= 1;
181bf215546Sopenharmony_ci    }
182bf215546Sopenharmony_ci    vstream->vap_prog_stream_cntl[i >> 1] |=
183bf215546Sopenharmony_ci        (R300_LAST_VEC << (i & 1 ? 16 : 0));
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci    vstream->count = (i >> 1) + 1;
186bf215546Sopenharmony_ci    r300_mark_atom_dirty(r300, &r300->vertex_stream_state);
187bf215546Sopenharmony_ci    r300->vertex_stream_state.size = (1 + vstream->count) * 2;
188bf215546Sopenharmony_ci}
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_cistatic void r300_rs_col(struct r300_rs_block* rs, int id, int ptr,
191bf215546Sopenharmony_ci                        enum r300_rs_swizzle swiz)
192bf215546Sopenharmony_ci{
193bf215546Sopenharmony_ci    rs->ip[id] |= R300_RS_COL_PTR(ptr);
194bf215546Sopenharmony_ci    if (swiz == SWIZ_0001) {
195bf215546Sopenharmony_ci        rs->ip[id] |= R300_RS_COL_FMT(R300_RS_COL_FMT_0001);
196bf215546Sopenharmony_ci    } else {
197bf215546Sopenharmony_ci        rs->ip[id] |= R300_RS_COL_FMT(R300_RS_COL_FMT_RGBA);
198bf215546Sopenharmony_ci    }
199bf215546Sopenharmony_ci    rs->inst[id] |= R300_RS_INST_COL_ID(id);
200bf215546Sopenharmony_ci}
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_cistatic void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset,
203bf215546Sopenharmony_ci                              enum r300_rs_col_write_type type)
204bf215546Sopenharmony_ci{
205bf215546Sopenharmony_ci    assert(type == WRITE_COLOR);
206bf215546Sopenharmony_ci    rs->inst[id] |= R300_RS_INST_COL_CN_WRITE |
207bf215546Sopenharmony_ci                    R300_RS_INST_COL_ADDR(fp_offset);
208bf215546Sopenharmony_ci}
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_cistatic void r300_rs_tex(struct r300_rs_block* rs, int id, int ptr,
211bf215546Sopenharmony_ci                        enum r300_rs_swizzle swiz)
212bf215546Sopenharmony_ci{
213bf215546Sopenharmony_ci    if (swiz == SWIZ_X001) {
214bf215546Sopenharmony_ci        rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
215bf215546Sopenharmony_ci                      R300_RS_SEL_S(R300_RS_SEL_C0) |
216bf215546Sopenharmony_ci                      R300_RS_SEL_T(R300_RS_SEL_K0) |
217bf215546Sopenharmony_ci                      R300_RS_SEL_R(R300_RS_SEL_K0) |
218bf215546Sopenharmony_ci                      R300_RS_SEL_Q(R300_RS_SEL_K1);
219bf215546Sopenharmony_ci    } else if (swiz == SWIZ_XY01) {
220bf215546Sopenharmony_ci        rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
221bf215546Sopenharmony_ci                      R300_RS_SEL_S(R300_RS_SEL_C0) |
222bf215546Sopenharmony_ci                      R300_RS_SEL_T(R300_RS_SEL_C1) |
223bf215546Sopenharmony_ci                      R300_RS_SEL_R(R300_RS_SEL_K0) |
224bf215546Sopenharmony_ci                      R300_RS_SEL_Q(R300_RS_SEL_K1);
225bf215546Sopenharmony_ci    } else {
226bf215546Sopenharmony_ci        rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
227bf215546Sopenharmony_ci                      R300_RS_SEL_S(R300_RS_SEL_C0) |
228bf215546Sopenharmony_ci                      R300_RS_SEL_T(R300_RS_SEL_C1) |
229bf215546Sopenharmony_ci                      R300_RS_SEL_R(R300_RS_SEL_C2) |
230bf215546Sopenharmony_ci                      R300_RS_SEL_Q(R300_RS_SEL_C3);
231bf215546Sopenharmony_ci    }
232bf215546Sopenharmony_ci    rs->inst[id] |= R300_RS_INST_TEX_ID(id);
233bf215546Sopenharmony_ci}
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_cistatic void r300_rs_tex_write(struct r300_rs_block* rs, int id, int fp_offset)
236bf215546Sopenharmony_ci{
237bf215546Sopenharmony_ci    rs->inst[id] |= R300_RS_INST_TEX_CN_WRITE |
238bf215546Sopenharmony_ci                    R300_RS_INST_TEX_ADDR(fp_offset);
239bf215546Sopenharmony_ci}
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_cistatic void r500_rs_col(struct r300_rs_block* rs, int id, int ptr,
242bf215546Sopenharmony_ci                        enum r300_rs_swizzle swiz)
243bf215546Sopenharmony_ci{
244bf215546Sopenharmony_ci    rs->ip[id] |= R500_RS_COL_PTR(ptr);
245bf215546Sopenharmony_ci    if (swiz == SWIZ_0001) {
246bf215546Sopenharmony_ci        rs->ip[id] |= R500_RS_COL_FMT(R300_RS_COL_FMT_0001);
247bf215546Sopenharmony_ci    } else {
248bf215546Sopenharmony_ci        rs->ip[id] |= R500_RS_COL_FMT(R300_RS_COL_FMT_RGBA);
249bf215546Sopenharmony_ci    }
250bf215546Sopenharmony_ci    rs->inst[id] |= R500_RS_INST_COL_ID(id);
251bf215546Sopenharmony_ci}
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_cistatic void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset,
254bf215546Sopenharmony_ci                              enum r300_rs_col_write_type type)
255bf215546Sopenharmony_ci{
256bf215546Sopenharmony_ci    if (type == WRITE_FACE)
257bf215546Sopenharmony_ci        rs->inst[id] |= R500_RS_INST_COL_CN_WRITE_BACKFACE |
258bf215546Sopenharmony_ci                        R500_RS_INST_COL_ADDR(fp_offset);
259bf215546Sopenharmony_ci    else
260bf215546Sopenharmony_ci        rs->inst[id] |= R500_RS_INST_COL_CN_WRITE |
261bf215546Sopenharmony_ci                        R500_RS_INST_COL_ADDR(fp_offset);
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci}
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_cistatic void r500_rs_tex(struct r300_rs_block* rs, int id, int ptr,
266bf215546Sopenharmony_ci			enum r300_rs_swizzle swiz)
267bf215546Sopenharmony_ci{
268bf215546Sopenharmony_ci    if (swiz == SWIZ_X001) {
269bf215546Sopenharmony_ci        rs->ip[id] |= R500_RS_SEL_S(ptr) |
270bf215546Sopenharmony_ci                      R500_RS_SEL_T(R500_RS_IP_PTR_K0) |
271bf215546Sopenharmony_ci                      R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
272bf215546Sopenharmony_ci                      R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
273bf215546Sopenharmony_ci    } else if (swiz == SWIZ_XY01) {
274bf215546Sopenharmony_ci        rs->ip[id] |= R500_RS_SEL_S(ptr) |
275bf215546Sopenharmony_ci                      R500_RS_SEL_T(ptr + 1) |
276bf215546Sopenharmony_ci                      R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
277bf215546Sopenharmony_ci                      R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
278bf215546Sopenharmony_ci    } else {
279bf215546Sopenharmony_ci        rs->ip[id] |= R500_RS_SEL_S(ptr) |
280bf215546Sopenharmony_ci                      R500_RS_SEL_T(ptr + 1) |
281bf215546Sopenharmony_ci                      R500_RS_SEL_R(ptr + 2) |
282bf215546Sopenharmony_ci                      R500_RS_SEL_Q(ptr + 3);
283bf215546Sopenharmony_ci    }
284bf215546Sopenharmony_ci    rs->inst[id] |= R500_RS_INST_TEX_ID(id);
285bf215546Sopenharmony_ci}
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_cistatic void r500_rs_tex_write(struct r300_rs_block* rs, int id, int fp_offset)
288bf215546Sopenharmony_ci{
289bf215546Sopenharmony_ci    rs->inst[id] |= R500_RS_INST_TEX_CN_WRITE |
290bf215546Sopenharmony_ci                    R500_RS_INST_TEX_ADDR(fp_offset);
291bf215546Sopenharmony_ci}
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci/* Set up the RS block.
294bf215546Sopenharmony_ci *
295bf215546Sopenharmony_ci * This is the part of the chipset that is responsible for linking vertex
296bf215546Sopenharmony_ci * and fragment shaders and stuffed texture coordinates.
297bf215546Sopenharmony_ci *
298bf215546Sopenharmony_ci * The rasterizer reads data from VAP, which produces vertex shader outputs,
299bf215546Sopenharmony_ci * and GA, which produces stuffed texture coordinates. VAP outputs have
300bf215546Sopenharmony_ci * precedence over GA. All outputs must be rasterized otherwise it locks up.
301bf215546Sopenharmony_ci * If there are more outputs rasterized than is set in VAP/GA, it locks up
302bf215546Sopenharmony_ci * too. The funky part is that this info has been pretty much obtained by trial
303bf215546Sopenharmony_ci * and error. */
304bf215546Sopenharmony_cistatic void r300_update_rs_block(struct r300_context *r300)
305bf215546Sopenharmony_ci{
306bf215546Sopenharmony_ci    struct r300_vertex_shader_code *vs = r300_vs(r300)->shader;
307bf215546Sopenharmony_ci    struct r300_shader_semantics *vs_outputs = &vs->outputs;
308bf215546Sopenharmony_ci    struct r300_shader_semantics *fs_inputs = &r300_fs(r300)->shader->inputs;
309bf215546Sopenharmony_ci    struct r300_rs_block rs = {0};
310bf215546Sopenharmony_ci    int i, col_count = 0, tex_count = 0, fp_offset = 0, count, loc = 0, tex_ptr = 0;
311bf215546Sopenharmony_ci    int gen_offset = 0;
312bf215546Sopenharmony_ci    void (*rX00_rs_col)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
313bf215546Sopenharmony_ci    void (*rX00_rs_col_write)(struct r300_rs_block*, int, int, enum r300_rs_col_write_type);
314bf215546Sopenharmony_ci    void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
315bf215546Sopenharmony_ci    void (*rX00_rs_tex_write)(struct r300_rs_block*, int, int);
316bf215546Sopenharmony_ci    boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
317bf215546Sopenharmony_ci                              vs_outputs->bcolor[1] != ATTR_UNUSED;
318bf215546Sopenharmony_ci    int *stream_loc_notcl = r300->stream_loc_notcl;
319bf215546Sopenharmony_ci    uint32_t stuffing_enable = 0;
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci    if (r300->screen->caps.is_r500) {
322bf215546Sopenharmony_ci        rX00_rs_col       = r500_rs_col;
323bf215546Sopenharmony_ci        rX00_rs_col_write = r500_rs_col_write;
324bf215546Sopenharmony_ci        rX00_rs_tex       = r500_rs_tex;
325bf215546Sopenharmony_ci        rX00_rs_tex_write = r500_rs_tex_write;
326bf215546Sopenharmony_ci    } else {
327bf215546Sopenharmony_ci        rX00_rs_col       = r300_rs_col;
328bf215546Sopenharmony_ci        rX00_rs_col_write = r300_rs_col_write;
329bf215546Sopenharmony_ci        rX00_rs_tex       = r300_rs_tex;
330bf215546Sopenharmony_ci        rX00_rs_tex_write = r300_rs_tex_write;
331bf215546Sopenharmony_ci    }
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci    /* 0x5555 copied from classic, which means:
334bf215546Sopenharmony_ci     * Select user color 0 for COLOR0 up to COLOR7.
335bf215546Sopenharmony_ci     * What the hell does that mean? */
336bf215546Sopenharmony_ci    rs.vap_vtx_state_cntl = 0x5555;
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci    /* The position is always present in VAP. */
339bf215546Sopenharmony_ci    rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_POS;
340bf215546Sopenharmony_ci    rs.vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
341bf215546Sopenharmony_ci    stream_loc_notcl[loc++] = 0;
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci    /* Set up the point size in VAP. */
344bf215546Sopenharmony_ci    if (vs_outputs->psize != ATTR_UNUSED) {
345bf215546Sopenharmony_ci        rs.vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
346bf215546Sopenharmony_ci        stream_loc_notcl[loc++] = 1;
347bf215546Sopenharmony_ci    }
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci    /* Set up and rasterize colors. */
350bf215546Sopenharmony_ci    for (i = 0; i < ATTR_COLOR_COUNT; i++) {
351bf215546Sopenharmony_ci        if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used ||
352bf215546Sopenharmony_ci            vs_outputs->color[1] != ATTR_UNUSED) {
353bf215546Sopenharmony_ci            /* Set up the color in VAP. */
354bf215546Sopenharmony_ci            rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR;
355bf215546Sopenharmony_ci            rs.vap_out_vtx_fmt[0] |=
356bf215546Sopenharmony_ci                    R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i;
357bf215546Sopenharmony_ci            stream_loc_notcl[loc++] = 2 + i;
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci            /* Rasterize it. */
360bf215546Sopenharmony_ci            rX00_rs_col(&rs, col_count, col_count, SWIZ_XYZW);
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci            /* Write it to the FS input register if it's needed by the FS. */
363bf215546Sopenharmony_ci            if (fs_inputs->color[i] != ATTR_UNUSED) {
364bf215546Sopenharmony_ci                rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_COLOR);
365bf215546Sopenharmony_ci                fp_offset++;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci                DBG(r300, DBG_RS,
368bf215546Sopenharmony_ci                    "r300: Rasterized color %i written to FS.\n", i);
369bf215546Sopenharmony_ci            } else {
370bf215546Sopenharmony_ci                DBG(r300, DBG_RS, "r300: Rasterized color %i unused.\n", i);
371bf215546Sopenharmony_ci            }
372bf215546Sopenharmony_ci            col_count++;
373bf215546Sopenharmony_ci        } else {
374bf215546Sopenharmony_ci            /* Skip the FS input register, leave it uninitialized. */
375bf215546Sopenharmony_ci            /* If we try to set it to (0,0,0,1), it will lock up. */
376bf215546Sopenharmony_ci            if (fs_inputs->color[i] != ATTR_UNUSED) {
377bf215546Sopenharmony_ci                fp_offset++;
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci                DBG(r300, DBG_RS, "r300: FS input color %i unassigned.\n",
380bf215546Sopenharmony_ci                    i);
381bf215546Sopenharmony_ci            }
382bf215546Sopenharmony_ci        }
383bf215546Sopenharmony_ci    }
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci    /* Set up back-face colors. The rasterizer will do the color selection
386bf215546Sopenharmony_ci     * automatically. */
387bf215546Sopenharmony_ci    if (any_bcolor_used) {
388bf215546Sopenharmony_ci        if (r300->two_sided_color) {
389bf215546Sopenharmony_ci            /* Rasterize as back-face colors. */
390bf215546Sopenharmony_ci            for (i = 0; i < ATTR_COLOR_COUNT; i++) {
391bf215546Sopenharmony_ci                rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR;
392bf215546Sopenharmony_ci                rs.vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i);
393bf215546Sopenharmony_ci                stream_loc_notcl[loc++] = 4 + i;
394bf215546Sopenharmony_ci            }
395bf215546Sopenharmony_ci        } else {
396bf215546Sopenharmony_ci            /* Rasterize two fake texcoords to prevent from the two-sided color
397bf215546Sopenharmony_ci             * selection. */
398bf215546Sopenharmony_ci            /* XXX Consider recompiling the vertex shader to save 2 RS units. */
399bf215546Sopenharmony_ci            for (i = 0; i < 2; i++) {
400bf215546Sopenharmony_ci                rs.vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << tex_count);
401bf215546Sopenharmony_ci                rs.vap_out_vtx_fmt[1] |= (4 << (3 * tex_count));
402bf215546Sopenharmony_ci                stream_loc_notcl[loc++] = 6 + tex_count;
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci                /* Rasterize it. */
405bf215546Sopenharmony_ci                rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_XYZW);
406bf215546Sopenharmony_ci                tex_count++;
407bf215546Sopenharmony_ci                tex_ptr += 4;
408bf215546Sopenharmony_ci            }
409bf215546Sopenharmony_ci        }
410bf215546Sopenharmony_ci    }
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci    /* gl_FrontFacing.
413bf215546Sopenharmony_ci     * Note that we can use either the two-sided color selection based on
414bf215546Sopenharmony_ci     * the front and back vertex shader colors, or gl_FrontFacing,
415bf215546Sopenharmony_ci     * but not both! It locks up otherwise.
416bf215546Sopenharmony_ci     *
417bf215546Sopenharmony_ci     * In Direct3D 9, the two-sided color selection can be used
418bf215546Sopenharmony_ci     * with shaders 2.0 only, while gl_FrontFacing can be used
419bf215546Sopenharmony_ci     * with shaders 3.0 only. The hardware apparently hasn't been designed
420bf215546Sopenharmony_ci     * to support both at the same time. */
421bf215546Sopenharmony_ci    if (r300->screen->caps.is_r500 && fs_inputs->face != ATTR_UNUSED &&
422bf215546Sopenharmony_ci        !(any_bcolor_used && r300->two_sided_color)) {
423bf215546Sopenharmony_ci        rX00_rs_col(&rs, col_count, col_count, SWIZ_XYZW);
424bf215546Sopenharmony_ci        rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_FACE);
425bf215546Sopenharmony_ci        fp_offset++;
426bf215546Sopenharmony_ci        col_count++;
427bf215546Sopenharmony_ci        DBG(r300, DBG_RS, "r300: Rasterized FACE written to FS.\n");
428bf215546Sopenharmony_ci    } else if (fs_inputs->face != ATTR_UNUSED) {
429bf215546Sopenharmony_ci        fprintf(stderr, "r300: ERROR: FS input FACE unassigned.\n");
430bf215546Sopenharmony_ci    }
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci    /* Re-use color varyings for texcoords if possible.
433bf215546Sopenharmony_ci     *
434bf215546Sopenharmony_ci     * The colors are interpolated as 20-bit floats (reduced precision),
435bf215546Sopenharmony_ci     * Use this hack only if there are too many generic varyings.
436bf215546Sopenharmony_ci     * (number of generic varyings + fog + wpos > 8) */
437bf215546Sopenharmony_ci    if (r300->screen->caps.is_r500 && !any_bcolor_used && !r300->flatshade &&
438bf215546Sopenharmony_ci	fs_inputs->face == ATTR_UNUSED &&
439bf215546Sopenharmony_ci        vs_outputs->num_generic + (vs_outputs->fog != ATTR_UNUSED) +
440bf215546Sopenharmony_ci        (fs_inputs->wpos != ATTR_UNUSED) > 8) {
441bf215546Sopenharmony_ci	for (i = 0; i < ATTR_GENERIC_COUNT && col_count < 2; i++) {
442bf215546Sopenharmony_ci	    /* Cannot use color varyings for sprite coords. */
443bf215546Sopenharmony_ci	    if (fs_inputs->generic[i] != ATTR_UNUSED &&
444bf215546Sopenharmony_ci		(r300->sprite_coord_enable & (1U << i)) && r300->is_point) {
445bf215546Sopenharmony_ci		break;
446bf215546Sopenharmony_ci	    }
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci	    if (vs_outputs->generic[i] != ATTR_UNUSED) {
449bf215546Sopenharmony_ci		/* Set up the color in VAP. */
450bf215546Sopenharmony_ci		rs.vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR;
451bf215546Sopenharmony_ci		rs.vap_out_vtx_fmt[0] |=
452bf215546Sopenharmony_ci			R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << col_count;
453bf215546Sopenharmony_ci		stream_loc_notcl[loc++] = 2 + col_count;
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci		/* Rasterize it. */
456bf215546Sopenharmony_ci		rX00_rs_col(&rs, col_count, col_count, SWIZ_XYZW);
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci		/* Write it to the FS input register if it's needed by the FS. */
459bf215546Sopenharmony_ci		if (fs_inputs->generic[i] != ATTR_UNUSED) {
460bf215546Sopenharmony_ci		    rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_COLOR);
461bf215546Sopenharmony_ci		    fp_offset++;
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci		    DBG(r300, DBG_RS,
464bf215546Sopenharmony_ci			"r300: Rasterized generic %i redirected to color %i and written to FS.\n",
465bf215546Sopenharmony_ci		        i, col_count);
466bf215546Sopenharmony_ci		} else {
467bf215546Sopenharmony_ci		    DBG(r300, DBG_RS, "r300: Rasterized generic %i redirected to color %i unused.\n",
468bf215546Sopenharmony_ci		        i, col_count);
469bf215546Sopenharmony_ci		}
470bf215546Sopenharmony_ci		col_count++;
471bf215546Sopenharmony_ci	    } else {
472bf215546Sopenharmony_ci		/* Skip the FS input register, leave it uninitialized. */
473bf215546Sopenharmony_ci		/* If we try to set it to (0,0,0,1), it will lock up. */
474bf215546Sopenharmony_ci		if (fs_inputs->generic[i] != ATTR_UNUSED) {
475bf215546Sopenharmony_ci		    fp_offset++;
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci		    DBG(r300, DBG_RS, "r300: FS input generic %i unassigned.\n", i);
478bf215546Sopenharmony_ci		}
479bf215546Sopenharmony_ci	    }
480bf215546Sopenharmony_ci	}
481bf215546Sopenharmony_ci	gen_offset = i;
482bf215546Sopenharmony_ci    }
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci    /* Rasterize texture coordinates. */
485bf215546Sopenharmony_ci    for (i = gen_offset; i < ATTR_GENERIC_COUNT && tex_count < 8; i++) {
486bf215546Sopenharmony_ci	boolean sprite_coord = false;
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci	if (fs_inputs->generic[i] != ATTR_UNUSED) {
489bf215546Sopenharmony_ci	    sprite_coord = !!(r300->sprite_coord_enable & (1 << i)) && r300->is_point;
490bf215546Sopenharmony_ci	}
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci        if (vs_outputs->generic[i] != ATTR_UNUSED || sprite_coord) {
493bf215546Sopenharmony_ci            if (!sprite_coord) {
494bf215546Sopenharmony_ci                /* Set up the texture coordinates in VAP. */
495bf215546Sopenharmony_ci                rs.vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << tex_count);
496bf215546Sopenharmony_ci                rs.vap_out_vtx_fmt[1] |= (4 << (3 * tex_count));
497bf215546Sopenharmony_ci                stream_loc_notcl[loc++] = 6 + tex_count;
498bf215546Sopenharmony_ci            } else
499bf215546Sopenharmony_ci                stuffing_enable |=
500bf215546Sopenharmony_ci                    R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (tex_count*2));
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci            /* Rasterize it. */
503bf215546Sopenharmony_ci            rX00_rs_tex(&rs, tex_count, tex_ptr,
504bf215546Sopenharmony_ci			sprite_coord ? SWIZ_XY01 : SWIZ_XYZW);
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci            /* Write it to the FS input register if it's needed by the FS. */
507bf215546Sopenharmony_ci            if (fs_inputs->generic[i] != ATTR_UNUSED) {
508bf215546Sopenharmony_ci                rX00_rs_tex_write(&rs, tex_count, fp_offset);
509bf215546Sopenharmony_ci                fp_offset++;
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci                DBG(r300, DBG_RS,
512bf215546Sopenharmony_ci                    "r300: Rasterized generic %i written to FS%s in texcoord %d.\n",
513bf215546Sopenharmony_ci                    i, sprite_coord ? " (sprite coord)" : "", tex_count);
514bf215546Sopenharmony_ci            } else {
515bf215546Sopenharmony_ci                DBG(r300, DBG_RS,
516bf215546Sopenharmony_ci                    "r300: Rasterized generic %i unused%s.\n",
517bf215546Sopenharmony_ci                    i, sprite_coord ? " (sprite coord)" : "");
518bf215546Sopenharmony_ci            }
519bf215546Sopenharmony_ci            tex_count++;
520bf215546Sopenharmony_ci            tex_ptr += sprite_coord ? 2 : 4;
521bf215546Sopenharmony_ci        } else {
522bf215546Sopenharmony_ci            /* Skip the FS input register, leave it uninitialized. */
523bf215546Sopenharmony_ci            /* If we try to set it to (0,0,0,1), it will lock up. */
524bf215546Sopenharmony_ci            if (fs_inputs->generic[i] != ATTR_UNUSED) {
525bf215546Sopenharmony_ci                fp_offset++;
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci                DBG(r300, DBG_RS, "r300: FS input generic %i unassigned%s.\n",
528bf215546Sopenharmony_ci                    i, sprite_coord ? " (sprite coord)" : "");
529bf215546Sopenharmony_ci            }
530bf215546Sopenharmony_ci        }
531bf215546Sopenharmony_ci    }
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci    for (; i < ATTR_GENERIC_COUNT; i++) {
534bf215546Sopenharmony_ci        if (fs_inputs->generic[i] != ATTR_UNUSED) {
535bf215546Sopenharmony_ci            fprintf(stderr, "r300: ERROR: FS input generic %i unassigned, "
536bf215546Sopenharmony_ci                    "not enough hardware slots (it's not a bug, do not "
537bf215546Sopenharmony_ci                    "report it).\n", i);
538bf215546Sopenharmony_ci        }
539bf215546Sopenharmony_ci    }
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci    /* Rasterize fog coordinates. */
542bf215546Sopenharmony_ci    if (vs_outputs->fog != ATTR_UNUSED && tex_count < 8) {
543bf215546Sopenharmony_ci        /* Set up the fog coordinates in VAP. */
544bf215546Sopenharmony_ci        rs.vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << tex_count);
545bf215546Sopenharmony_ci        rs.vap_out_vtx_fmt[1] |= (4 << (3 * tex_count));
546bf215546Sopenharmony_ci        stream_loc_notcl[loc++] = 6 + tex_count;
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci        /* Rasterize it. */
549bf215546Sopenharmony_ci        rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_X001);
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci        /* Write it to the FS input register if it's needed by the FS. */
552bf215546Sopenharmony_ci        if (fs_inputs->fog != ATTR_UNUSED) {
553bf215546Sopenharmony_ci            rX00_rs_tex_write(&rs, tex_count, fp_offset);
554bf215546Sopenharmony_ci            fp_offset++;
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci            DBG(r300, DBG_RS, "r300: Rasterized fog written to FS.\n");
557bf215546Sopenharmony_ci        } else {
558bf215546Sopenharmony_ci            DBG(r300, DBG_RS, "r300: Rasterized fog unused.\n");
559bf215546Sopenharmony_ci        }
560bf215546Sopenharmony_ci        tex_count++;
561bf215546Sopenharmony_ci        tex_ptr += 4;
562bf215546Sopenharmony_ci    } else {
563bf215546Sopenharmony_ci        /* Skip the FS input register, leave it uninitialized. */
564bf215546Sopenharmony_ci        /* If we try to set it to (0,0,0,1), it will lock up. */
565bf215546Sopenharmony_ci        if (fs_inputs->fog != ATTR_UNUSED) {
566bf215546Sopenharmony_ci            fp_offset++;
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci            if (tex_count < 8) {
569bf215546Sopenharmony_ci                DBG(r300, DBG_RS, "r300: FS input fog unassigned.\n");
570bf215546Sopenharmony_ci            } else {
571bf215546Sopenharmony_ci                fprintf(stderr, "r300: ERROR: FS input fog unassigned, "
572bf215546Sopenharmony_ci                        "not enough hardware slots. (it's not a bug, "
573bf215546Sopenharmony_ci                        "do not report it)\n");
574bf215546Sopenharmony_ci            }
575bf215546Sopenharmony_ci        }
576bf215546Sopenharmony_ci    }
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci    /* Rasterize WPOS. */
579bf215546Sopenharmony_ci    /* Don't set it in VAP if the FS doesn't need it. */
580bf215546Sopenharmony_ci    if (fs_inputs->wpos != ATTR_UNUSED && tex_count < 8) {
581bf215546Sopenharmony_ci        /* Set up the WPOS coordinates in VAP. */
582bf215546Sopenharmony_ci        rs.vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << tex_count);
583bf215546Sopenharmony_ci        rs.vap_out_vtx_fmt[1] |= (4 << (3 * tex_count));
584bf215546Sopenharmony_ci        stream_loc_notcl[loc++] = 6 + tex_count;
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci        /* Rasterize it. */
587bf215546Sopenharmony_ci        rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_XYZW);
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_ci        /* Write it to the FS input register. */
590bf215546Sopenharmony_ci        rX00_rs_tex_write(&rs, tex_count, fp_offset);
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci        DBG(r300, DBG_RS, "r300: Rasterized WPOS written to FS.\n");
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ci        fp_offset++;
595bf215546Sopenharmony_ci        tex_count++;
596bf215546Sopenharmony_ci        tex_ptr += 4;
597bf215546Sopenharmony_ci    } else {
598bf215546Sopenharmony_ci        if (fs_inputs->wpos != ATTR_UNUSED && tex_count >= 8) {
599bf215546Sopenharmony_ci            fprintf(stderr, "r300: ERROR: FS input WPOS unassigned, "
600bf215546Sopenharmony_ci                    "not enough hardware slots. (it's not a bug, do not "
601bf215546Sopenharmony_ci                    "report it)\n");
602bf215546Sopenharmony_ci        }
603bf215546Sopenharmony_ci    }
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci    /* Invalidate the rest of the no-TCL (GA) stream locations. */
606bf215546Sopenharmony_ci    for (; loc < 16;) {
607bf215546Sopenharmony_ci        stream_loc_notcl[loc++] = -1;
608bf215546Sopenharmony_ci    }
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci    /* Rasterize at least one color, or bad things happen. */
611bf215546Sopenharmony_ci    if (col_count == 0 && tex_count == 0) {
612bf215546Sopenharmony_ci        rX00_rs_col(&rs, 0, 0, SWIZ_0001);
613bf215546Sopenharmony_ci        col_count++;
614bf215546Sopenharmony_ci
615bf215546Sopenharmony_ci        DBG(r300, DBG_RS, "r300: Rasterized color 0 to prevent lockups.\n");
616bf215546Sopenharmony_ci    }
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci    DBG(r300, DBG_RS, "r300: --- Rasterizer status ---: colors: %i, "
619bf215546Sopenharmony_ci        "generics: %i.\n", col_count, tex_count);
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci    rs.count = MIN2(tex_ptr, 32) | (col_count << R300_IC_COUNT_SHIFT) |
622bf215546Sopenharmony_ci        R300_HIRES_EN;
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci    count = MAX3(col_count, tex_count, 1);
625bf215546Sopenharmony_ci    rs.inst_count = count - 1;
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci    /* set the GB enable flags */
628bf215546Sopenharmony_ci    if (r300->sprite_coord_enable && r300->is_point)
629bf215546Sopenharmony_ci	stuffing_enable |= R300_GB_POINT_STUFF_ENABLE;
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_ci    rs.gb_enable = stuffing_enable;
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci    /* Now, after all that, see if we actually need to update the state. */
634bf215546Sopenharmony_ci    if (memcmp(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block))) {
635bf215546Sopenharmony_ci        memcpy(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block));
636bf215546Sopenharmony_ci        r300->rs_block_state.size = 13 + count*2;
637bf215546Sopenharmony_ci    }
638bf215546Sopenharmony_ci}
639bf215546Sopenharmony_ci
640bf215546Sopenharmony_cistatic void rgba_to_bgra(float color[4])
641bf215546Sopenharmony_ci{
642bf215546Sopenharmony_ci    float x = color[0];
643bf215546Sopenharmony_ci    color[0] = color[2];
644bf215546Sopenharmony_ci    color[2] = x;
645bf215546Sopenharmony_ci}
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_cistatic uint32_t r300_get_border_color(enum pipe_format format,
648bf215546Sopenharmony_ci                                      const float border[4],
649bf215546Sopenharmony_ci                                      boolean is_r500)
650bf215546Sopenharmony_ci{
651bf215546Sopenharmony_ci    const struct util_format_description *desc;
652bf215546Sopenharmony_ci    float border_swizzled[4] = {0};
653bf215546Sopenharmony_ci    union util_color uc = {0};
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci    desc = util_format_description(format);
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci    /* Do depth formats first. */
658bf215546Sopenharmony_ci    if (util_format_is_depth_or_stencil(format)) {
659bf215546Sopenharmony_ci        switch (format) {
660bf215546Sopenharmony_ci        case PIPE_FORMAT_Z16_UNORM:
661bf215546Sopenharmony_ci            return util_pack_z(PIPE_FORMAT_Z16_UNORM, border[0]);
662bf215546Sopenharmony_ci        case PIPE_FORMAT_X8Z24_UNORM:
663bf215546Sopenharmony_ci        case PIPE_FORMAT_S8_UINT_Z24_UNORM:
664bf215546Sopenharmony_ci            if (is_r500) {
665bf215546Sopenharmony_ci                return util_pack_z(PIPE_FORMAT_X8Z24_UNORM, border[0]);
666bf215546Sopenharmony_ci            } else {
667bf215546Sopenharmony_ci                return util_pack_z(PIPE_FORMAT_Z16_UNORM, border[0]) << 16;
668bf215546Sopenharmony_ci            }
669bf215546Sopenharmony_ci        default:
670bf215546Sopenharmony_ci            assert(0);
671bf215546Sopenharmony_ci            return 0;
672bf215546Sopenharmony_ci        }
673bf215546Sopenharmony_ci    }
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_ci    /* Apply inverse swizzle of the format. */
676bf215546Sopenharmony_ci    util_format_unswizzle_4f(border_swizzled, border, desc->swizzle);
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci    /* Compressed formats. */
679bf215546Sopenharmony_ci    if (util_format_is_compressed(format)) {
680bf215546Sopenharmony_ci        switch (format) {
681bf215546Sopenharmony_ci        case PIPE_FORMAT_RGTC1_SNORM:
682bf215546Sopenharmony_ci        case PIPE_FORMAT_LATC1_SNORM:
683bf215546Sopenharmony_ci            border_swizzled[0] = border_swizzled[0] < 0 ?
684bf215546Sopenharmony_ci                                 border_swizzled[0]*0.5+1 :
685bf215546Sopenharmony_ci                                 border_swizzled[0]*0.5;
686bf215546Sopenharmony_ci            FALLTHROUGH;
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci        case PIPE_FORMAT_RGTC1_UNORM:
689bf215546Sopenharmony_ci        case PIPE_FORMAT_LATC1_UNORM:
690bf215546Sopenharmony_ci            /* Add 1/32 to round the border color instead of truncating. */
691bf215546Sopenharmony_ci            /* The Y component is used for the border color. */
692bf215546Sopenharmony_ci            border_swizzled[1] = border_swizzled[0] + 1.0f/32;
693bf215546Sopenharmony_ci            util_pack_color(border_swizzled, PIPE_FORMAT_B4G4R4A4_UNORM, &uc);
694bf215546Sopenharmony_ci            return uc.ui[0];
695bf215546Sopenharmony_ci        case PIPE_FORMAT_RGTC2_SNORM:
696bf215546Sopenharmony_ci        case PIPE_FORMAT_LATC2_SNORM:
697bf215546Sopenharmony_ci            util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_SNORM, &uc);
698bf215546Sopenharmony_ci            return uc.ui[0];
699bf215546Sopenharmony_ci        case PIPE_FORMAT_RGTC2_UNORM:
700bf215546Sopenharmony_ci        case PIPE_FORMAT_LATC2_UNORM:
701bf215546Sopenharmony_ci            util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_UNORM, &uc);
702bf215546Sopenharmony_ci            return uc.ui[0];
703bf215546Sopenharmony_ci        case PIPE_FORMAT_DXT1_SRGB:
704bf215546Sopenharmony_ci        case PIPE_FORMAT_DXT1_SRGBA:
705bf215546Sopenharmony_ci        case PIPE_FORMAT_DXT3_SRGBA:
706bf215546Sopenharmony_ci        case PIPE_FORMAT_DXT5_SRGBA:
707bf215546Sopenharmony_ci            util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_SRGB, &uc);
708bf215546Sopenharmony_ci            return uc.ui[0];
709bf215546Sopenharmony_ci        default:
710bf215546Sopenharmony_ci            util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
711bf215546Sopenharmony_ci            return uc.ui[0];
712bf215546Sopenharmony_ci        }
713bf215546Sopenharmony_ci    }
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci    switch (desc->channel[0].size) {
716bf215546Sopenharmony_ci        case 2:
717bf215546Sopenharmony_ci            rgba_to_bgra(border_swizzled);
718bf215546Sopenharmony_ci            util_pack_color(border_swizzled, PIPE_FORMAT_B2G3R3_UNORM, &uc);
719bf215546Sopenharmony_ci            break;
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci        case 4:
722bf215546Sopenharmony_ci            rgba_to_bgra(border_swizzled);
723bf215546Sopenharmony_ci            util_pack_color(border_swizzled, PIPE_FORMAT_B4G4R4A4_UNORM, &uc);
724bf215546Sopenharmony_ci            break;
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci        case 5:
727bf215546Sopenharmony_ci            rgba_to_bgra(border_swizzled);
728bf215546Sopenharmony_ci            if (desc->channel[1].size == 5) {
729bf215546Sopenharmony_ci                util_pack_color(border_swizzled, PIPE_FORMAT_B5G5R5A1_UNORM, &uc);
730bf215546Sopenharmony_ci            } else if (desc->channel[1].size == 6) {
731bf215546Sopenharmony_ci                util_pack_color(border_swizzled, PIPE_FORMAT_B5G6R5_UNORM, &uc);
732bf215546Sopenharmony_ci            } else {
733bf215546Sopenharmony_ci                assert(0);
734bf215546Sopenharmony_ci            }
735bf215546Sopenharmony_ci            break;
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci        default:
738bf215546Sopenharmony_ci        case 8:
739bf215546Sopenharmony_ci            if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) {
740bf215546Sopenharmony_ci                util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_SNORM, &uc);
741bf215546Sopenharmony_ci            } else if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
742bf215546Sopenharmony_ci                if (desc->nr_channels == 2) {
743bf215546Sopenharmony_ci                    border_swizzled[3] = border_swizzled[1];
744bf215546Sopenharmony_ci                    util_pack_color(border_swizzled, PIPE_FORMAT_L8A8_SRGB, &uc);
745bf215546Sopenharmony_ci                } else {
746bf215546Sopenharmony_ci                    util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_SRGB, &uc);
747bf215546Sopenharmony_ci                }
748bf215546Sopenharmony_ci            } else {
749bf215546Sopenharmony_ci                util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_UNORM, &uc);
750bf215546Sopenharmony_ci            }
751bf215546Sopenharmony_ci            break;
752bf215546Sopenharmony_ci
753bf215546Sopenharmony_ci        case 10:
754bf215546Sopenharmony_ci            util_pack_color(border_swizzled, PIPE_FORMAT_R10G10B10A2_UNORM, &uc);
755bf215546Sopenharmony_ci            break;
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ci        case 16:
758bf215546Sopenharmony_ci            if (desc->nr_channels <= 2) {
759bf215546Sopenharmony_ci                if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
760bf215546Sopenharmony_ci                    util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_FLOAT, &uc);
761bf215546Sopenharmony_ci                } else if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) {
762bf215546Sopenharmony_ci                    util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_SNORM, &uc);
763bf215546Sopenharmony_ci                } else {
764bf215546Sopenharmony_ci                    util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_UNORM, &uc);
765bf215546Sopenharmony_ci                }
766bf215546Sopenharmony_ci            } else {
767bf215546Sopenharmony_ci                if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) {
768bf215546Sopenharmony_ci                    util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_SNORM, &uc);
769bf215546Sopenharmony_ci                } else {
770bf215546Sopenharmony_ci                    util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_UNORM, &uc);
771bf215546Sopenharmony_ci                }
772bf215546Sopenharmony_ci            }
773bf215546Sopenharmony_ci            break;
774bf215546Sopenharmony_ci
775bf215546Sopenharmony_ci        case 32:
776bf215546Sopenharmony_ci            if (desc->nr_channels == 1) {
777bf215546Sopenharmony_ci                util_pack_color(border_swizzled, PIPE_FORMAT_R32_FLOAT, &uc);
778bf215546Sopenharmony_ci            } else {
779bf215546Sopenharmony_ci                util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_UNORM, &uc);
780bf215546Sopenharmony_ci            }
781bf215546Sopenharmony_ci            break;
782bf215546Sopenharmony_ci    }
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci    return uc.ui[0];
785bf215546Sopenharmony_ci}
786bf215546Sopenharmony_ci
787bf215546Sopenharmony_cistatic void r300_merge_textures_and_samplers(struct r300_context* r300)
788bf215546Sopenharmony_ci{
789bf215546Sopenharmony_ci    struct r300_textures_state *state =
790bf215546Sopenharmony_ci        (struct r300_textures_state*)r300->textures_state.state;
791bf215546Sopenharmony_ci    struct r300_texture_sampler_state *texstate;
792bf215546Sopenharmony_ci    struct r300_sampler_state *sampler;
793bf215546Sopenharmony_ci    struct r300_sampler_view *view;
794bf215546Sopenharmony_ci    struct r300_resource *tex;
795bf215546Sopenharmony_ci    unsigned base_level, min_level, level_count, i, j, size;
796bf215546Sopenharmony_ci    unsigned count = MIN2(state->sampler_view_count,
797bf215546Sopenharmony_ci                          state->sampler_state_count);
798bf215546Sopenharmony_ci    boolean has_us_format = r300->screen->caps.has_us_format;
799bf215546Sopenharmony_ci
800bf215546Sopenharmony_ci    /* The KIL opcode fix, see below. */
801bf215546Sopenharmony_ci    if (!count && !r300->screen->caps.is_r500)
802bf215546Sopenharmony_ci        count = 1;
803bf215546Sopenharmony_ci
804bf215546Sopenharmony_ci    state->tx_enable = 0;
805bf215546Sopenharmony_ci    state->count = 0;
806bf215546Sopenharmony_ci    size = 2;
807bf215546Sopenharmony_ci
808bf215546Sopenharmony_ci    for (i = 0; i < count; i++) {
809bf215546Sopenharmony_ci        if (state->sampler_views[i] && state->sampler_states[i]) {
810bf215546Sopenharmony_ci            state->tx_enable |= 1U << i;
811bf215546Sopenharmony_ci
812bf215546Sopenharmony_ci            view = state->sampler_views[i];
813bf215546Sopenharmony_ci            tex = r300_resource(view->base.texture);
814bf215546Sopenharmony_ci            sampler = state->sampler_states[i];
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ci            texstate = &state->regs[i];
817bf215546Sopenharmony_ci            texstate->format = view->format;
818bf215546Sopenharmony_ci            texstate->filter0 = sampler->filter0;
819bf215546Sopenharmony_ci            texstate->filter1 = sampler->filter1;
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_ci            /* Set the border color. */
822bf215546Sopenharmony_ci            texstate->border_color =
823bf215546Sopenharmony_ci                r300_get_border_color(view->base.format,
824bf215546Sopenharmony_ci                                      sampler->state.border_color.f,
825bf215546Sopenharmony_ci                                      r300->screen->caps.is_r500);
826bf215546Sopenharmony_ci
827bf215546Sopenharmony_ci            /* determine min/max levels */
828bf215546Sopenharmony_ci            base_level = view->base.u.tex.first_level;
829bf215546Sopenharmony_ci            min_level = sampler->min_lod;
830bf215546Sopenharmony_ci            level_count = MIN3(sampler->max_lod,
831bf215546Sopenharmony_ci                               tex->b.last_level - base_level,
832bf215546Sopenharmony_ci                               view->base.u.tex.last_level - base_level);
833bf215546Sopenharmony_ci
834bf215546Sopenharmony_ci            if (base_level + min_level) {
835bf215546Sopenharmony_ci                unsigned offset;
836bf215546Sopenharmony_ci
837bf215546Sopenharmony_ci                if (tex->tex.is_npot) {
838bf215546Sopenharmony_ci                    /* Even though we do not implement mipmapping for NPOT
839bf215546Sopenharmony_ci                     * textures, we should at least honor the minimum level
840bf215546Sopenharmony_ci                     * which is allowed to be displayed. We do this by setting up
841bf215546Sopenharmony_ci                     * an i-th mipmap level as the zero level. */
842bf215546Sopenharmony_ci                    base_level += min_level;
843bf215546Sopenharmony_ci                }
844bf215546Sopenharmony_ci                offset = tex->tex.offset_in_bytes[base_level];
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_ci                r300_texture_setup_format_state(r300->screen, tex,
847bf215546Sopenharmony_ci                                                view->base.format,
848bf215546Sopenharmony_ci                                                base_level,
849bf215546Sopenharmony_ci                                                view->width0_override,
850bf215546Sopenharmony_ci		                                view->height0_override,
851bf215546Sopenharmony_ci                                                &texstate->format);
852bf215546Sopenharmony_ci                texstate->format.tile_config |= offset & 0xffffffe0;
853bf215546Sopenharmony_ci                assert((offset & 0x1f) == 0);
854bf215546Sopenharmony_ci            }
855bf215546Sopenharmony_ci
856bf215546Sopenharmony_ci            /* Assign a texture cache region. */
857bf215546Sopenharmony_ci            texstate->format.format1 |= view->texcache_region;
858bf215546Sopenharmony_ci
859bf215546Sopenharmony_ci            /* Depth textures are kinda special. */
860bf215546Sopenharmony_ci            if (util_format_is_depth_or_stencil(view->base.format)) {
861bf215546Sopenharmony_ci                unsigned char depth_swizzle[4];
862bf215546Sopenharmony_ci
863bf215546Sopenharmony_ci                if (!r300->screen->caps.is_r500 &&
864bf215546Sopenharmony_ci                    util_format_get_blocksizebits(view->base.format) == 32) {
865bf215546Sopenharmony_ci                    /* X24x8 is sampled as Y16X16 on r3xx-r4xx.
866bf215546Sopenharmony_ci                     * The depth here is at the Y component. */
867bf215546Sopenharmony_ci                    for (j = 0; j < 4; j++)
868bf215546Sopenharmony_ci                        depth_swizzle[j] = PIPE_SWIZZLE_Y;
869bf215546Sopenharmony_ci                } else {
870bf215546Sopenharmony_ci                    for (j = 0; j < 4; j++)
871bf215546Sopenharmony_ci                        depth_swizzle[j] = PIPE_SWIZZLE_X;
872bf215546Sopenharmony_ci                }
873bf215546Sopenharmony_ci
874bf215546Sopenharmony_ci                /* If compare mode is disabled, sampler view swizzles
875bf215546Sopenharmony_ci                 * are stored in the format.
876bf215546Sopenharmony_ci                 * Otherwise, the swizzles must be applied after the compare
877bf215546Sopenharmony_ci                 * mode in the fragment shader. */
878bf215546Sopenharmony_ci                if (sampler->state.compare_mode == PIPE_TEX_COMPARE_NONE) {
879bf215546Sopenharmony_ci                    texstate->format.format1 |=
880bf215546Sopenharmony_ci                        r300_get_swizzle_combined(depth_swizzle,
881bf215546Sopenharmony_ci                                                  view->swizzle, FALSE);
882bf215546Sopenharmony_ci                } else {
883bf215546Sopenharmony_ci                    texstate->format.format1 |=
884bf215546Sopenharmony_ci                        r300_get_swizzle_combined(depth_swizzle, NULL, FALSE);
885bf215546Sopenharmony_ci                }
886bf215546Sopenharmony_ci            }
887bf215546Sopenharmony_ci
888bf215546Sopenharmony_ci            if (r300->screen->caps.dxtc_swizzle &&
889bf215546Sopenharmony_ci                util_format_is_compressed(view->base.format)) {
890bf215546Sopenharmony_ci                texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE;
891bf215546Sopenharmony_ci            }
892bf215546Sopenharmony_ci
893bf215546Sopenharmony_ci            /* to emulate 1D textures through 2D ones correctly */
894bf215546Sopenharmony_ci            if (tex->b.target == PIPE_TEXTURE_1D) {
895bf215546Sopenharmony_ci                texstate->filter0 &= ~R300_TX_WRAP_T_MASK;
896bf215546Sopenharmony_ci                texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
897bf215546Sopenharmony_ci            }
898bf215546Sopenharmony_ci
899bf215546Sopenharmony_ci            /* The hardware doesn't like CLAMP and CLAMP_TO_BORDER
900bf215546Sopenharmony_ci             * for the 3rd coordinate if the texture isn't 3D. */
901bf215546Sopenharmony_ci            if (tex->b.target != PIPE_TEXTURE_3D) {
902bf215546Sopenharmony_ci                texstate->filter0 &= ~R300_TX_WRAP_R_MASK;
903bf215546Sopenharmony_ci            }
904bf215546Sopenharmony_ci
905bf215546Sopenharmony_ci            if (tex->tex.is_npot) {
906bf215546Sopenharmony_ci                /* NPOT textures don't support mip filter, unfortunately.
907bf215546Sopenharmony_ci                 * This prevents incorrect rendering. */
908bf215546Sopenharmony_ci                texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK;
909bf215546Sopenharmony_ci
910bf215546Sopenharmony_ci                /* Mask out the mirrored flag. */
911bf215546Sopenharmony_ci                if (texstate->filter0 & R300_TX_WRAP_S(R300_TX_MIRRORED)) {
912bf215546Sopenharmony_ci                    texstate->filter0 &= ~R300_TX_WRAP_S(R300_TX_MIRRORED);
913bf215546Sopenharmony_ci                }
914bf215546Sopenharmony_ci                if (texstate->filter0 & R300_TX_WRAP_T(R300_TX_MIRRORED)) {
915bf215546Sopenharmony_ci                    texstate->filter0 &= ~R300_TX_WRAP_T(R300_TX_MIRRORED);
916bf215546Sopenharmony_ci                }
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_ci                /* Change repeat to clamp-to-edge.
919bf215546Sopenharmony_ci                 * (the repeat bit has a value of 0, no masking needed). */
920bf215546Sopenharmony_ci                if ((texstate->filter0 & R300_TX_WRAP_S_MASK) ==
921bf215546Sopenharmony_ci                    R300_TX_WRAP_S(R300_TX_REPEAT)) {
922bf215546Sopenharmony_ci                    texstate->filter0 |= R300_TX_WRAP_S(R300_TX_CLAMP_TO_EDGE);
923bf215546Sopenharmony_ci                }
924bf215546Sopenharmony_ci                if ((texstate->filter0 & R300_TX_WRAP_T_MASK) ==
925bf215546Sopenharmony_ci                    R300_TX_WRAP_T(R300_TX_REPEAT)) {
926bf215546Sopenharmony_ci                    texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
927bf215546Sopenharmony_ci                }
928bf215546Sopenharmony_ci            } else {
929bf215546Sopenharmony_ci                /* the MAX_MIP level is the largest (finest) one */
930bf215546Sopenharmony_ci                texstate->format.format0 |= R300_TX_NUM_LEVELS(level_count);
931bf215546Sopenharmony_ci                texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level);
932bf215546Sopenharmony_ci            }
933bf215546Sopenharmony_ci
934bf215546Sopenharmony_ci            /* Float textures only support nearest and mip-nearest filtering. */
935bf215546Sopenharmony_ci            if (util_format_is_float(view->base.format)) {
936bf215546Sopenharmony_ci                /* No MAG linear filtering. */
937bf215546Sopenharmony_ci                if ((texstate->filter0 & R300_TX_MAG_FILTER_MASK) ==
938bf215546Sopenharmony_ci                    R300_TX_MAG_FILTER_LINEAR) {
939bf215546Sopenharmony_ci                    texstate->filter0 &= ~R300_TX_MAG_FILTER_MASK;
940bf215546Sopenharmony_ci                    texstate->filter0 |= R300_TX_MAG_FILTER_NEAREST;
941bf215546Sopenharmony_ci                }
942bf215546Sopenharmony_ci                /* No MIN linear filtering. */
943bf215546Sopenharmony_ci                if ((texstate->filter0 & R300_TX_MIN_FILTER_MASK) ==
944bf215546Sopenharmony_ci                    R300_TX_MIN_FILTER_LINEAR) {
945bf215546Sopenharmony_ci                    texstate->filter0 &= ~R300_TX_MIN_FILTER_MASK;
946bf215546Sopenharmony_ci                    texstate->filter0 |= R300_TX_MIN_FILTER_NEAREST;
947bf215546Sopenharmony_ci                }
948bf215546Sopenharmony_ci                /* No mipmap linear filtering. */
949bf215546Sopenharmony_ci                if ((texstate->filter0 & R300_TX_MIN_FILTER_MIP_MASK) ==
950bf215546Sopenharmony_ci                    R300_TX_MIN_FILTER_MIP_LINEAR) {
951bf215546Sopenharmony_ci                    texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK;
952bf215546Sopenharmony_ci                    texstate->filter0 |= R300_TX_MIN_FILTER_MIP_NEAREST;
953bf215546Sopenharmony_ci                }
954bf215546Sopenharmony_ci                /* No anisotropic filtering. */
955bf215546Sopenharmony_ci                texstate->filter0 &= ~R300_TX_MAX_ANISO_MASK;
956bf215546Sopenharmony_ci                texstate->filter1 &= ~R500_TX_MAX_ANISO_MASK;
957bf215546Sopenharmony_ci                texstate->filter1 &= ~R500_TX_ANISO_HIGH_QUALITY;
958bf215546Sopenharmony_ci            }
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_ci            texstate->filter0 |= i << 28;
961bf215546Sopenharmony_ci
962bf215546Sopenharmony_ci            size += 16 + (has_us_format ? 2 : 0);
963bf215546Sopenharmony_ci            state->count = i+1;
964bf215546Sopenharmony_ci        } else {
965bf215546Sopenharmony_ci            /* For the KIL opcode to work on r3xx-r4xx, the texture unit
966bf215546Sopenharmony_ci             * assigned to this opcode (it's always the first one) must be
967bf215546Sopenharmony_ci             * enabled. Otherwise the opcode doesn't work.
968bf215546Sopenharmony_ci             *
969bf215546Sopenharmony_ci             * In order to not depend on the fragment shader, we just make
970bf215546Sopenharmony_ci             * the first unit enabled all the time. */
971bf215546Sopenharmony_ci            if (i == 0 && !r300->screen->caps.is_r500) {
972bf215546Sopenharmony_ci                pipe_sampler_view_reference(
973bf215546Sopenharmony_ci                        (struct pipe_sampler_view**)&state->sampler_views[i],
974bf215546Sopenharmony_ci                        &r300->texkill_sampler->base);
975bf215546Sopenharmony_ci
976bf215546Sopenharmony_ci                state->tx_enable |= 1U << i;
977bf215546Sopenharmony_ci
978bf215546Sopenharmony_ci                texstate = &state->regs[i];
979bf215546Sopenharmony_ci
980bf215546Sopenharmony_ci                /* Just set some valid state. */
981bf215546Sopenharmony_ci                texstate->format = r300->texkill_sampler->format;
982bf215546Sopenharmony_ci                texstate->filter0 =
983bf215546Sopenharmony_ci                        r300_translate_tex_filters(PIPE_TEX_FILTER_NEAREST,
984bf215546Sopenharmony_ci                                                   PIPE_TEX_FILTER_NEAREST,
985bf215546Sopenharmony_ci                                                   PIPE_TEX_FILTER_NEAREST,
986bf215546Sopenharmony_ci                                                   FALSE);
987bf215546Sopenharmony_ci                texstate->filter1 = 0;
988bf215546Sopenharmony_ci                texstate->border_color = 0;
989bf215546Sopenharmony_ci
990bf215546Sopenharmony_ci                texstate->filter0 |= i << 28;
991bf215546Sopenharmony_ci                size += 16 + (has_us_format ? 2 : 0);
992bf215546Sopenharmony_ci                state->count = i+1;
993bf215546Sopenharmony_ci            }
994bf215546Sopenharmony_ci        }
995bf215546Sopenharmony_ci    }
996bf215546Sopenharmony_ci
997bf215546Sopenharmony_ci    r300->textures_state.size = size;
998bf215546Sopenharmony_ci
999bf215546Sopenharmony_ci    /* Pick a fragment shader based on either the texture compare state
1000bf215546Sopenharmony_ci     * or the uses_pitch flag or some other external state. */
1001bf215546Sopenharmony_ci    if (count &&
1002bf215546Sopenharmony_ci        r300->fs_status == FRAGMENT_SHADER_VALID) {
1003bf215546Sopenharmony_ci        r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY;
1004bf215546Sopenharmony_ci    }
1005bf215546Sopenharmony_ci}
1006bf215546Sopenharmony_ci
1007bf215546Sopenharmony_cistatic void r300_decompress_depth_textures(struct r300_context *r300)
1008bf215546Sopenharmony_ci{
1009bf215546Sopenharmony_ci    struct r300_textures_state *state =
1010bf215546Sopenharmony_ci        (struct r300_textures_state*)r300->textures_state.state;
1011bf215546Sopenharmony_ci    struct pipe_resource *tex;
1012bf215546Sopenharmony_ci    unsigned count = MIN2(state->sampler_view_count,
1013bf215546Sopenharmony_ci                          state->sampler_state_count);
1014bf215546Sopenharmony_ci    unsigned i;
1015bf215546Sopenharmony_ci
1016bf215546Sopenharmony_ci    if (!r300->locked_zbuffer) {
1017bf215546Sopenharmony_ci        return;
1018bf215546Sopenharmony_ci    }
1019bf215546Sopenharmony_ci
1020bf215546Sopenharmony_ci    for (i = 0; i < count; i++) {
1021bf215546Sopenharmony_ci        if (state->sampler_views[i] && state->sampler_states[i]) {
1022bf215546Sopenharmony_ci            tex = state->sampler_views[i]->base.texture;
1023bf215546Sopenharmony_ci
1024bf215546Sopenharmony_ci            if (tex == r300->locked_zbuffer->texture) {
1025bf215546Sopenharmony_ci                r300_decompress_zmask_locked(r300);
1026bf215546Sopenharmony_ci                return;
1027bf215546Sopenharmony_ci            }
1028bf215546Sopenharmony_ci        }
1029bf215546Sopenharmony_ci    }
1030bf215546Sopenharmony_ci}
1031bf215546Sopenharmony_ci
1032bf215546Sopenharmony_cistatic void r300_validate_fragment_shader(struct r300_context *r300)
1033bf215546Sopenharmony_ci{
1034bf215546Sopenharmony_ci    struct pipe_framebuffer_state *fb = r300->fb_state.state;
1035bf215546Sopenharmony_ci
1036bf215546Sopenharmony_ci    if (r300->fs.state && r300->fs_status != FRAGMENT_SHADER_VALID) {
1037bf215546Sopenharmony_ci        struct r300_fragment_program_external_state state;
1038bf215546Sopenharmony_ci        memset(&state, 0, sizeof(state));
1039bf215546Sopenharmony_ci        r300_fragment_program_get_external_state(r300, &state);
1040bf215546Sopenharmony_ci
1041bf215546Sopenharmony_ci        /* Pick the fragment shader based on external states.
1042bf215546Sopenharmony_ci         * Then mark the state dirty if the fragment shader is either dirty
1043bf215546Sopenharmony_ci         * or the function r300_pick_fragment_shader changed the shader. */
1044bf215546Sopenharmony_ci        if (r300_pick_fragment_shader(r300, r300_fs(r300), &state) ||
1045bf215546Sopenharmony_ci            r300->fs_status == FRAGMENT_SHADER_DIRTY) {
1046bf215546Sopenharmony_ci            /* Mark the state atom as dirty. */
1047bf215546Sopenharmony_ci            r300_mark_fs_code_dirty(r300);
1048bf215546Sopenharmony_ci
1049bf215546Sopenharmony_ci            /* Does Multiwrite need to be changed? */
1050bf215546Sopenharmony_ci            if (fb->nr_cbufs > 1) {
1051bf215546Sopenharmony_ci                boolean new_multiwrite =
1052bf215546Sopenharmony_ci                    r300_fragment_shader_writes_all(r300_fs(r300));
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_ci                if (r300->fb_multiwrite != new_multiwrite) {
1055bf215546Sopenharmony_ci                    r300->fb_multiwrite = new_multiwrite;
1056bf215546Sopenharmony_ci                    r300_mark_fb_state_dirty(r300, R300_CHANGED_MULTIWRITE);
1057bf215546Sopenharmony_ci                }
1058bf215546Sopenharmony_ci            }
1059bf215546Sopenharmony_ci        }
1060bf215546Sopenharmony_ci        r300->fs_status = FRAGMENT_SHADER_VALID;
1061bf215546Sopenharmony_ci    }
1062bf215546Sopenharmony_ci}
1063bf215546Sopenharmony_ci
1064bf215546Sopenharmony_cistatic void r300_pick_vertex_shader(struct r300_context *r300)
1065bf215546Sopenharmony_ci{
1066bf215546Sopenharmony_ci    struct r300_vertex_shader_code *ptr;
1067bf215546Sopenharmony_ci    struct r300_vertex_shader *vs = r300_vs(r300);
1068bf215546Sopenharmony_ci
1069bf215546Sopenharmony_ci    if (r300->vs_state.state) {
1070bf215546Sopenharmony_ci        bool wpos = r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED;
1071bf215546Sopenharmony_ci
1072bf215546Sopenharmony_ci        if (!vs->first) {
1073bf215546Sopenharmony_ci            /* Build the vertex shader for the first time. */
1074bf215546Sopenharmony_ci            vs->first = vs->shader = CALLOC_STRUCT(r300_vertex_shader_code);
1075bf215546Sopenharmony_ci            vs->first->wpos = wpos;
1076bf215546Sopenharmony_ci            r300_translate_vertex_shader(r300, vs);
1077bf215546Sopenharmony_ci            if (!vs->first->dummy)
1078bf215546Sopenharmony_ci                r300_mark_atom_dirty(r300, &r300->rs_block_state);
1079bf215546Sopenharmony_ci            return;
1080bf215546Sopenharmony_ci        }
1081bf215546Sopenharmony_ci        /* Pick the vertex shader based on whether we need wpos */
1082bf215546Sopenharmony_ci        if (vs->first->wpos != wpos) {
1083bf215546Sopenharmony_ci            if (vs->first->next && vs->first->next->wpos == wpos) {
1084bf215546Sopenharmony_ci                ptr = vs->first->next;
1085bf215546Sopenharmony_ci                vs->first->next = NULL;
1086bf215546Sopenharmony_ci                ptr->next = vs->first;
1087bf215546Sopenharmony_ci                vs->first = vs->shader = ptr;
1088bf215546Sopenharmony_ci            } else {
1089bf215546Sopenharmony_ci                ptr = CALLOC_STRUCT(r300_vertex_shader_code);
1090bf215546Sopenharmony_ci                ptr->next = vs->first;
1091bf215546Sopenharmony_ci                vs->first = vs->shader = ptr;
1092bf215546Sopenharmony_ci                vs->shader->wpos = wpos;
1093bf215546Sopenharmony_ci                r300_translate_vertex_shader(r300, vs);
1094bf215546Sopenharmony_ci            }
1095bf215546Sopenharmony_ci            if (!vs->first->dummy)
1096bf215546Sopenharmony_ci                r300_mark_atom_dirty(r300, &r300->rs_block_state);
1097bf215546Sopenharmony_ci        }
1098bf215546Sopenharmony_ci    }
1099bf215546Sopenharmony_ci}
1100bf215546Sopenharmony_ci
1101bf215546Sopenharmony_civoid r300_update_derived_state(struct r300_context* r300)
1102bf215546Sopenharmony_ci{
1103bf215546Sopenharmony_ci    if (r300->textures_state.dirty) {
1104bf215546Sopenharmony_ci        r300_decompress_depth_textures(r300);
1105bf215546Sopenharmony_ci        r300_merge_textures_and_samplers(r300);
1106bf215546Sopenharmony_ci    }
1107bf215546Sopenharmony_ci
1108bf215546Sopenharmony_ci    r300_validate_fragment_shader(r300);
1109bf215546Sopenharmony_ci    if (r300->screen->caps.has_tcl)
1110bf215546Sopenharmony_ci        r300_pick_vertex_shader(r300);
1111bf215546Sopenharmony_ci
1112bf215546Sopenharmony_ci    if (r300->rs_block_state.dirty) {
1113bf215546Sopenharmony_ci        r300_update_rs_block(r300);
1114bf215546Sopenharmony_ci
1115bf215546Sopenharmony_ci        if (r300->draw) {
1116bf215546Sopenharmony_ci            memset(&r300->vertex_info, 0, sizeof(struct vertex_info));
1117bf215546Sopenharmony_ci            r300_draw_emit_all_attribs(r300);
1118bf215546Sopenharmony_ci            draw_compute_vertex_size(&r300->vertex_info);
1119bf215546Sopenharmony_ci            r300_swtcl_vertex_psc(r300);
1120bf215546Sopenharmony_ci        }
1121bf215546Sopenharmony_ci    }
1122bf215546Sopenharmony_ci
1123bf215546Sopenharmony_ci    r300_update_hyperz_state(r300);
1124bf215546Sopenharmony_ci}
1125