~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/r300/compiler/radeon_program_tex.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2010 Corbin Simpson
3
 
 * Copyright (C) 2010 Marek Olšák <maraeo@gmail.com>
4
 
 *
5
 
 * All Rights Reserved.
6
 
 *
7
 
 * Permission is hereby granted, free of charge, to any person obtaining
8
 
 * a copy of this software and associated documentation files (the
9
 
 * "Software"), to deal in the Software without restriction, including
10
 
 * without limitation the rights to use, copy, modify, merge, publish,
11
 
 * distribute, sublicense, and/or sell copies of the Software, and to
12
 
 * permit persons to whom the Software is furnished to do so, subject to
13
 
 * the following conditions:
14
 
 *
15
 
 * The above copyright notice and this permission notice (including the
16
 
 * next paragraph) shall be included in all copies or substantial
17
 
 * portions of the Software.
18
 
 *
19
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
 
 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
23
 
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
 
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
 
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 
 *
27
 
 */
28
 
 
29
 
#include "radeon_program_tex.h"
30
 
 
31
 
#include "radeon_compiler_util.h"
32
 
 
33
 
/* Series of transformations to be done on textures. */
34
 
 
35
 
static struct rc_src_register shadow_fail_value(struct r300_fragment_program_compiler *compiler,
36
 
                                                int tmu)
37
 
{
38
 
        struct rc_src_register reg = { 0, 0, 0, 0, 0, 0 };
39
 
 
40
 
        reg.File = RC_FILE_NONE;
41
 
        reg.Swizzle = combine_swizzles(RC_SWIZZLE_0000,
42
 
                                compiler->state.unit[tmu].texture_swizzle);
43
 
        return reg;
44
 
}
45
 
 
46
 
static struct rc_src_register shadow_pass_value(struct r300_fragment_program_compiler *compiler,
47
 
                                                int tmu)
48
 
{
49
 
        struct rc_src_register reg = { 0, 0, 0, 0, 0, 0 };
50
 
 
51
 
        reg.File = RC_FILE_NONE;
52
 
        reg.Swizzle = combine_swizzles(RC_SWIZZLE_1111,
53
 
                                compiler->state.unit[tmu].texture_swizzle);
54
 
        return reg;
55
 
}
56
 
 
57
 
static void scale_texcoords(struct r300_fragment_program_compiler *compiler,
58
 
                            struct rc_instruction *inst,
59
 
                            unsigned state_constant)
60
 
{
61
 
        struct rc_instruction *inst_mov;
62
 
 
63
 
        unsigned temp = rc_find_free_temporary(&compiler->Base);
64
 
 
65
 
        inst_mov = rc_insert_new_instruction(&compiler->Base, inst->Prev);
66
 
 
67
 
        inst_mov->U.I.Opcode = RC_OPCODE_MUL;
68
 
        inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
69
 
        inst_mov->U.I.DstReg.Index = temp;
70
 
        inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
71
 
        inst_mov->U.I.SrcReg[1].File = RC_FILE_CONSTANT;
72
 
        inst_mov->U.I.SrcReg[1].Index =
73
 
                        rc_constants_add_state(&compiler->Base.Program.Constants,
74
 
                                               state_constant, inst->U.I.TexSrcUnit);
75
 
 
76
 
        reset_srcreg(&inst->U.I.SrcReg[0]);
77
 
        inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
78
 
        inst->U.I.SrcReg[0].Index = temp;
79
 
}
80
 
 
81
 
static void projective_divide(struct r300_fragment_program_compiler *compiler,
82
 
                              struct rc_instruction *inst)
83
 
{
84
 
        struct rc_instruction *inst_mul, *inst_rcp;
85
 
 
86
 
        unsigned temp = rc_find_free_temporary(&compiler->Base);
87
 
 
88
 
        inst_rcp = rc_insert_new_instruction(&compiler->Base, inst->Prev);
89
 
        inst_rcp->U.I.Opcode = RC_OPCODE_RCP;
90
 
        inst_rcp->U.I.DstReg.File = RC_FILE_TEMPORARY;
91
 
        inst_rcp->U.I.DstReg.Index = temp;
92
 
        inst_rcp->U.I.DstReg.WriteMask = RC_MASK_W;
93
 
        inst_rcp->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
94
 
        /* Because the input can be arbitrarily swizzled,
95
 
         * read the component mapped to W. */
96
 
        inst_rcp->U.I.SrcReg[0].Swizzle =
97
 
                RC_MAKE_SWIZZLE_SMEAR(GET_SWZ(inst->U.I.SrcReg[0].Swizzle, 3));
98
 
 
99
 
        inst_mul = rc_insert_new_instruction(&compiler->Base, inst->Prev);
100
 
        inst_mul->U.I.Opcode = RC_OPCODE_MUL;
101
 
        inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY;
102
 
        inst_mul->U.I.DstReg.Index = temp;
103
 
        inst_mul->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
104
 
        inst_mul->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
105
 
        inst_mul->U.I.SrcReg[1].Index = temp;
106
 
        inst_mul->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_WWWW;
107
 
 
108
 
        reset_srcreg(&inst->U.I.SrcReg[0]);
109
 
        inst->U.I.Opcode = RC_OPCODE_TEX;
110
 
        inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
111
 
        inst->U.I.SrcReg[0].Index = temp;
112
 
}
113
 
 
114
 
/**
115
 
 * Transform TEX, TXP, TXB, and KIL instructions in the following ways:
116
 
 *  - implement texture compare (shadow extensions)
117
 
 *  - extract non-native source / destination operands
118
 
 *  - premultiply texture coordinates for RECT
119
 
 *  - extract operand swizzles
120
 
 *  - introduce a temporary register when write masks are needed
121
 
 */
122
 
int radeonTransformTEX(
123
 
        struct radeon_compiler * c,
124
 
        struct rc_instruction * inst,
125
 
        void* data)
126
 
{
127
 
        struct r300_fragment_program_compiler *compiler =
128
 
                (struct r300_fragment_program_compiler*)data;
129
 
        rc_wrap_mode wrapmode = compiler->state.unit[inst->U.I.TexSrcUnit].wrap_mode;
130
 
        int is_rect = inst->U.I.TexSrcTarget == RC_TEXTURE_RECT;
131
 
 
132
 
        if (inst->U.I.Opcode != RC_OPCODE_TEX &&
133
 
                inst->U.I.Opcode != RC_OPCODE_TXB &&
134
 
                inst->U.I.Opcode != RC_OPCODE_TXP &&
135
 
                inst->U.I.Opcode != RC_OPCODE_TXD &&
136
 
                inst->U.I.Opcode != RC_OPCODE_TXL &&
137
 
                inst->U.I.Opcode != RC_OPCODE_KIL)
138
 
                return 0;
139
 
 
140
 
        /* ARB_shadow & EXT_shadow_funcs */
141
 
        if (inst->U.I.Opcode != RC_OPCODE_KIL &&
142
 
                ((c->Program.ShadowSamplers & (1U << inst->U.I.TexSrcUnit)) ||
143
 
                 (compiler->state.unit[inst->U.I.TexSrcUnit].compare_mode_enabled))) {
144
 
                rc_compare_func comparefunc = compiler->state.unit[inst->U.I.TexSrcUnit].texture_compare_func;
145
 
 
146
 
                if (comparefunc == RC_COMPARE_FUNC_NEVER || comparefunc == RC_COMPARE_FUNC_ALWAYS) {
147
 
                        inst->U.I.Opcode = RC_OPCODE_MOV;
148
 
 
149
 
                        if (comparefunc == RC_COMPARE_FUNC_ALWAYS) {
150
 
                                inst->U.I.SrcReg[0] = shadow_pass_value(compiler, inst->U.I.TexSrcUnit);
151
 
                        } else {
152
 
                                inst->U.I.SrcReg[0] = shadow_fail_value(compiler, inst->U.I.TexSrcUnit);
153
 
                        }
154
 
 
155
 
                        return 1;
156
 
                } else {
157
 
                        struct rc_instruction * inst_rcp = NULL;
158
 
                        struct rc_instruction *inst_mul, *inst_add, *inst_cmp;
159
 
                        unsigned tmp_texsample;
160
 
                        unsigned tmp_sum;
161
 
                        int pass, fail;
162
 
 
163
 
                        /* Save the output register. */
164
 
                        struct rc_dst_register output_reg = inst->U.I.DstReg;
165
 
                        unsigned saturate_mode = inst->U.I.SaturateMode;
166
 
 
167
 
                        /* Redirect TEX to a new temp. */
168
 
                        tmp_texsample = rc_find_free_temporary(c);
169
 
                        inst->U.I.SaturateMode = 0;
170
 
                        inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
171
 
                        inst->U.I.DstReg.Index = tmp_texsample;
172
 
                        inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
173
 
 
174
 
                        tmp_sum = rc_find_free_temporary(c);
175
 
 
176
 
                        if (inst->U.I.Opcode == RC_OPCODE_TXP) {
177
 
                                /* Compute 1/W. */
178
 
                                inst_rcp = rc_insert_new_instruction(c, inst);
179
 
                                inst_rcp->U.I.Opcode = RC_OPCODE_RCP;
180
 
                                inst_rcp->U.I.DstReg.File = RC_FILE_TEMPORARY;
181
 
                                inst_rcp->U.I.DstReg.Index = tmp_sum;
182
 
                                inst_rcp->U.I.DstReg.WriteMask = RC_MASK_W;
183
 
                                inst_rcp->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
184
 
                                inst_rcp->U.I.SrcReg[0].Swizzle =
185
 
                                        RC_MAKE_SWIZZLE_SMEAR(GET_SWZ(inst->U.I.SrcReg[0].Swizzle, 3));
186
 
                        }
187
 
 
188
 
                        /* Divide Z by W (if it's TXP) and saturate. */
189
 
                        inst_mul = rc_insert_new_instruction(c, inst_rcp ? inst_rcp : inst);
190
 
                        inst_mul->U.I.Opcode = inst->U.I.Opcode == RC_OPCODE_TXP ? RC_OPCODE_MUL : RC_OPCODE_MOV;
191
 
                        inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY;
192
 
                        inst_mul->U.I.DstReg.Index = tmp_sum;
193
 
                        inst_mul->U.I.DstReg.WriteMask = RC_MASK_W;
194
 
                        inst_mul->U.I.SaturateMode = RC_SATURATE_ZERO_ONE;
195
 
                        inst_mul->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
196
 
                        inst_mul->U.I.SrcReg[0].Swizzle =
197
 
                                RC_MAKE_SWIZZLE_SMEAR(GET_SWZ(inst->U.I.SrcReg[0].Swizzle, 2));
198
 
                        if (inst->U.I.Opcode == RC_OPCODE_TXP) {
199
 
                                inst_mul->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
200
 
                                inst_mul->U.I.SrcReg[1].Index = tmp_sum;
201
 
                                inst_mul->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_WWWW;
202
 
                        }
203
 
 
204
 
                        /* Add the depth texture value. */
205
 
                        inst_add = rc_insert_new_instruction(c, inst_mul);
206
 
                        inst_add->U.I.Opcode = RC_OPCODE_ADD;
207
 
                        inst_add->U.I.DstReg.File = RC_FILE_TEMPORARY;
208
 
                        inst_add->U.I.DstReg.Index = tmp_sum;
209
 
                        inst_add->U.I.DstReg.WriteMask = RC_MASK_W;
210
 
                        inst_add->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
211
 
                        inst_add->U.I.SrcReg[0].Index = tmp_sum;
212
 
                        inst_add->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_WWWW;
213
 
                        inst_add->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
214
 
                        inst_add->U.I.SrcReg[1].Index = tmp_texsample;
215
 
                        inst_add->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XXXX;
216
 
 
217
 
                        /* Note that SrcReg[0] is r, SrcReg[1] is tex and:
218
 
                         *   LESS:    r  < tex  <=>      -tex+r < 0
219
 
                         *   GEQUAL:  r >= tex  <=> not (-tex+r < 0)
220
 
                         *   GREATER: r  > tex  <=>       tex-r < 0
221
 
                         *   LEQUAL:  r <= tex  <=> not ( tex-r < 0)
222
 
                         *   EQUAL:   GEQUAL
223
 
                         *   NOTEQUAL:LESS
224
 
                         */
225
 
 
226
 
                        /* This negates either r or tex: */
227
 
                        if (comparefunc == RC_COMPARE_FUNC_LESS || comparefunc == RC_COMPARE_FUNC_GEQUAL ||
228
 
                            comparefunc == RC_COMPARE_FUNC_EQUAL || comparefunc == RC_COMPARE_FUNC_NOTEQUAL)
229
 
                                inst_add->U.I.SrcReg[1].Negate = inst_add->U.I.SrcReg[1].Negate ^ RC_MASK_XYZW;
230
 
                        else
231
 
                                inst_add->U.I.SrcReg[0].Negate = inst_add->U.I.SrcReg[0].Negate ^ RC_MASK_XYZW;
232
 
 
233
 
                        /* This negates the whole expresion: */
234
 
                        if (comparefunc == RC_COMPARE_FUNC_LESS || comparefunc == RC_COMPARE_FUNC_GREATER ||
235
 
                            comparefunc == RC_COMPARE_FUNC_NOTEQUAL) {
236
 
                                pass = 1;
237
 
                                fail = 2;
238
 
                        } else {
239
 
                                pass = 2;
240
 
                                fail = 1;
241
 
                        }
242
 
 
243
 
                        inst_cmp = rc_insert_new_instruction(c, inst_add);
244
 
                        inst_cmp->U.I.Opcode = RC_OPCODE_CMP;
245
 
                        inst_cmp->U.I.SaturateMode = saturate_mode;
246
 
                        inst_cmp->U.I.DstReg = output_reg;
247
 
                        inst_cmp->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
248
 
                        inst_cmp->U.I.SrcReg[0].Index = tmp_sum;
249
 
                        inst_cmp->U.I.SrcReg[0].Swizzle =
250
 
                                        combine_swizzles(RC_SWIZZLE_WWWW,
251
 
                                                         compiler->state.unit[inst->U.I.TexSrcUnit].texture_swizzle);
252
 
                        inst_cmp->U.I.SrcReg[pass] = shadow_pass_value(compiler, inst->U.I.TexSrcUnit);
253
 
                        inst_cmp->U.I.SrcReg[fail] = shadow_fail_value(compiler, inst->U.I.TexSrcUnit);
254
 
 
255
 
                        assert(tmp_texsample != tmp_sum);
256
 
                }
257
 
        }
258
 
 
259
 
        /* R300 cannot sample from rectangles and the wrap mode fallback needs
260
 
         * normalized coordinates anyway. */
261
 
        if (inst->U.I.Opcode != RC_OPCODE_KIL &&
262
 
            is_rect && (!c->is_r500 || wrapmode != RC_WRAP_NONE)) {
263
 
                scale_texcoords(compiler, inst, RC_STATE_R300_TEXRECT_FACTOR);
264
 
                inst->U.I.TexSrcTarget = RC_TEXTURE_2D;
265
 
        }
266
 
 
267
 
        /* Divide by W if needed. */
268
 
        if (inst->U.I.Opcode == RC_OPCODE_TXP &&
269
 
            (wrapmode == RC_WRAP_REPEAT || wrapmode == RC_WRAP_MIRRORED_REPEAT ||
270
 
             compiler->state.unit[inst->U.I.TexSrcUnit].clamp_and_scale_before_fetch)) {
271
 
                projective_divide(compiler, inst);
272
 
        }
273
 
 
274
 
        /* Texture wrap modes don't work on NPOT textures.
275
 
         *
276
 
         * Non-wrapped/clamped texcoords with NPOT are free in HW. Repeat and
277
 
         * mirroring are not. If we need to repeat, we do:
278
 
         *
279
 
         * MUL temp, texcoord, <scaling factor constant>
280
 
         * FRC temp, temp ; Discard integer portion of coords
281
 
         *
282
 
         * This gives us coords in [0, 1].
283
 
         *
284
 
         * Mirroring is trickier. We're going to start out like repeat:
285
 
         *
286
 
         * MUL temp, texcoord, <scaling factor constant> ; De-mirror across axes
287
 
         * MUL temp, temp, 0.5 ; Pattern repeats in [0, 2]
288
 
         *                            ; so scale to [0, 1]
289
 
         * FRC temp, temp ; Make the pattern repeat
290
 
         * MAD temp, temp, 2, -1 ; Move the pattern to [-1, 1]
291
 
         * ADD temp, 1, -abs(temp) ; Now comes a neat trick: use abs to mirror the pattern.
292
 
         *                              ; The pattern is backwards, so reverse it (1-x).
293
 
         *
294
 
         * This gives us coords in [0, 1].
295
 
         *
296
 
         * ~ C & M. ;)
297
 
         */
298
 
        if (inst->U.I.Opcode != RC_OPCODE_KIL &&
299
 
            wrapmode != RC_WRAP_NONE) {
300
 
                struct rc_instruction *inst_mov;
301
 
                unsigned temp = rc_find_free_temporary(c);
302
 
 
303
 
                if (wrapmode == RC_WRAP_REPEAT) {
304
 
                        /* Both instructions will be paired up. */
305
 
                        struct rc_instruction *inst_frc = rc_insert_new_instruction(c, inst->Prev);
306
 
 
307
 
                        inst_frc->U.I.Opcode = RC_OPCODE_FRC;
308
 
                        inst_frc->U.I.DstReg.File = RC_FILE_TEMPORARY;
309
 
                        inst_frc->U.I.DstReg.Index = temp;
310
 
                        inst_frc->U.I.DstReg.WriteMask = RC_MASK_XYZ;
311
 
                        inst_frc->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
312
 
                } else if (wrapmode == RC_WRAP_MIRRORED_REPEAT) {
313
 
                        /*
314
 
                         * Function:
315
 
                         *   f(v) = 1 - abs(frac(v * 0.5) * 2 - 1)
316
 
                         *
317
 
                         * Code:
318
 
                         *   MUL temp, src0, 0.5
319
 
                         *   FRC temp, temp
320
 
                         *   MAD temp, temp, 2, -1
321
 
                         *   ADD temp, 1, -abs(temp)
322
 
                         */
323
 
 
324
 
                        struct rc_instruction *inst_mul, *inst_frc, *inst_mad, *inst_add;
325
 
                        unsigned two, two_swizzle;
326
 
 
327
 
                        inst_mul = rc_insert_new_instruction(c, inst->Prev);
328
 
 
329
 
                        inst_mul->U.I.Opcode = RC_OPCODE_MUL;
330
 
                        inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY;
331
 
                        inst_mul->U.I.DstReg.Index = temp;
332
 
                        inst_mul->U.I.DstReg.WriteMask = RC_MASK_XYZ;
333
 
                        inst_mul->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
334
 
                        inst_mul->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_HHHH;
335
 
 
336
 
                        inst_frc = rc_insert_new_instruction(c, inst->Prev);
337
 
 
338
 
                        inst_frc->U.I.Opcode = RC_OPCODE_FRC;
339
 
                        inst_frc->U.I.DstReg.File = RC_FILE_TEMPORARY;
340
 
                        inst_frc->U.I.DstReg.Index = temp;
341
 
                        inst_frc->U.I.DstReg.WriteMask = RC_MASK_XYZ;
342
 
                        inst_frc->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
343
 
                        inst_frc->U.I.SrcReg[0].Index = temp;
344
 
                        inst_frc->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZ0;
345
 
 
346
 
                        two = rc_constants_add_immediate_scalar(&c->Program.Constants, 2, &two_swizzle);
347
 
                        inst_mad = rc_insert_new_instruction(c, inst->Prev);
348
 
 
349
 
                        inst_mad->U.I.Opcode = RC_OPCODE_MAD;
350
 
                        inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY;
351
 
                        inst_mad->U.I.DstReg.Index = temp;
352
 
                        inst_mad->U.I.DstReg.WriteMask = RC_MASK_XYZ;
353
 
                        inst_mad->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
354
 
                        inst_mad->U.I.SrcReg[0].Index = temp;
355
 
                        inst_mad->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZ0;
356
 
                        inst_mad->U.I.SrcReg[1].File = RC_FILE_CONSTANT;
357
 
                        inst_mad->U.I.SrcReg[1].Index = two;
358
 
                        inst_mad->U.I.SrcReg[1].Swizzle = two_swizzle;
359
 
                        inst_mad->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_1111;
360
 
                        inst_mad->U.I.SrcReg[2].Negate = RC_MASK_XYZ;
361
 
 
362
 
                        inst_add = rc_insert_new_instruction(c, inst->Prev);
363
 
 
364
 
                        inst_add->U.I.Opcode = RC_OPCODE_ADD;
365
 
                        inst_add->U.I.DstReg.File = RC_FILE_TEMPORARY;
366
 
                        inst_add->U.I.DstReg.Index = temp;
367
 
                        inst_add->U.I.DstReg.WriteMask = RC_MASK_XYZ;
368
 
                        inst_add->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111;
369
 
                        inst_add->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
370
 
                        inst_add->U.I.SrcReg[1].Index = temp;
371
 
                        inst_add->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZ0;
372
 
                        inst_add->U.I.SrcReg[1].Abs = 1;
373
 
                        inst_add->U.I.SrcReg[1].Negate = RC_MASK_XYZ;
374
 
                } else if (wrapmode == RC_WRAP_MIRRORED_CLAMP) {
375
 
                        /*
376
 
                         * Mirrored clamp modes are bloody simple, we just use abs
377
 
                         * to mirror [0, 1] into [-1, 0]. This works for
378
 
                         * all modes i.e. CLAMP, CLAMP_TO_EDGE, and CLAMP_TO_BORDER.
379
 
                         */
380
 
                        struct rc_instruction *inst_mov;
381
 
 
382
 
                        inst_mov = rc_insert_new_instruction(c, inst->Prev);
383
 
 
384
 
                        inst_mov->U.I.Opcode = RC_OPCODE_MOV;
385
 
                        inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
386
 
                        inst_mov->U.I.DstReg.Index = temp;
387
 
                        inst_mov->U.I.DstReg.WriteMask = RC_MASK_XYZ;
388
 
                        inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
389
 
                        inst_mov->U.I.SrcReg[0].Abs = 1;
390
 
                }
391
 
 
392
 
                /* Preserve W for TXP/TXB. */
393
 
                inst_mov = rc_insert_new_instruction(c, inst->Prev);
394
 
 
395
 
                inst_mov->U.I.Opcode = RC_OPCODE_MOV;
396
 
                inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
397
 
                inst_mov->U.I.DstReg.Index = temp;
398
 
                inst_mov->U.I.DstReg.WriteMask = RC_MASK_W;
399
 
                inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
400
 
 
401
 
                reset_srcreg(&inst->U.I.SrcReg[0]);
402
 
                inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
403
 
                inst->U.I.SrcReg[0].Index = temp;
404
 
        }
405
 
 
406
 
        /* NPOT -> POT conversion for 3D textures. */
407
 
        if (inst->U.I.Opcode != RC_OPCODE_KIL &&
408
 
            compiler->state.unit[inst->U.I.TexSrcUnit].clamp_and_scale_before_fetch) {
409
 
                struct rc_instruction *inst_mov;
410
 
                unsigned temp = rc_find_free_temporary(c);
411
 
 
412
 
                /* Saturate XYZ. */
413
 
                inst_mov = rc_insert_new_instruction(c, inst->Prev);
414
 
                inst_mov->U.I.Opcode = RC_OPCODE_MOV;
415
 
                inst_mov->U.I.SaturateMode = RC_SATURATE_ZERO_ONE;
416
 
                inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
417
 
                inst_mov->U.I.DstReg.Index = temp;
418
 
                inst_mov->U.I.DstReg.WriteMask = RC_MASK_XYZ;
419
 
                inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
420
 
 
421
 
                /* Copy W. */
422
 
                inst_mov = rc_insert_new_instruction(c, inst->Prev);
423
 
                inst_mov->U.I.Opcode = RC_OPCODE_MOV;
424
 
                inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
425
 
                inst_mov->U.I.DstReg.Index = temp;
426
 
                inst_mov->U.I.DstReg.WriteMask = RC_MASK_W;
427
 
                inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
428
 
 
429
 
                reset_srcreg(&inst->U.I.SrcReg[0]);
430
 
                inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
431
 
                inst->U.I.SrcReg[0].Index = temp;
432
 
 
433
 
                scale_texcoords(compiler, inst, RC_STATE_R300_TEXSCALE_FACTOR);
434
 
        }
435
 
 
436
 
        /* Cannot write texture to output registers or with saturate (all chips),
437
 
         * or with masks (non-r500). */
438
 
        if (inst->U.I.Opcode != RC_OPCODE_KIL &&
439
 
                (inst->U.I.DstReg.File != RC_FILE_TEMPORARY ||
440
 
                 inst->U.I.SaturateMode ||
441
 
                 (!c->is_r500 && inst->U.I.DstReg.WriteMask != RC_MASK_XYZW))) {
442
 
                struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst);
443
 
 
444
 
                inst_mov->U.I.Opcode = RC_OPCODE_MOV;
445
 
                inst_mov->U.I.SaturateMode = inst->U.I.SaturateMode;
446
 
                inst_mov->U.I.DstReg = inst->U.I.DstReg;
447
 
                inst_mov->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
448
 
                inst_mov->U.I.SrcReg[0].Index = rc_find_free_temporary(c);
449
 
 
450
 
                inst->U.I.SaturateMode = 0;
451
 
                inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
452
 
                inst->U.I.DstReg.Index = inst_mov->U.I.SrcReg[0].Index;
453
 
                inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
454
 
        }
455
 
 
456
 
        /* Cannot read texture coordinate from constants file */
457
 
        if (inst->U.I.SrcReg[0].File != RC_FILE_TEMPORARY && inst->U.I.SrcReg[0].File != RC_FILE_INPUT) {
458
 
                struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst->Prev);
459
 
 
460
 
                inst_mov->U.I.Opcode = RC_OPCODE_MOV;
461
 
                inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
462
 
                inst_mov->U.I.DstReg.Index = rc_find_free_temporary(c);
463
 
                inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
464
 
 
465
 
                reset_srcreg(&inst->U.I.SrcReg[0]);
466
 
                inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
467
 
                inst->U.I.SrcReg[0].Index = inst_mov->U.I.DstReg.Index;
468
 
        }
469
 
 
470
 
        return 1;
471
 
}