cell: initial work to support multi-texture
[mesa.git] / src / gallium / drivers / cell / spu / spu_per_fragment_op.c
1 /*
2 * (C) Copyright IBM Corporation 2008
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file spu_per_fragment_op.c
27 * SPU implementation various per-fragment operations.
28 *
29 * \author Ian Romanick <idr@us.ibm.com>
30 */
31
32 #include "pipe/p_format.h"
33 #include "spu_main.h"
34 #include "spu_per_fragment_op.h"
35
36 #define ZERO 0x80
37
38 static void
39 read_ds_quad(tile_t *buffer, unsigned x, unsigned y,
40 enum pipe_format depth_format, qword *depth,
41 qword *stencil)
42 {
43 const int ix = x / 2;
44 const int iy = y / 2;
45
46 switch (depth_format) {
47 case PIPE_FORMAT_Z16_UNORM: {
48 qword *ptr = (qword *) &buffer->us8[iy][ix / 2];
49
50 const qword shuf_vec = (qword) {
51 ZERO, ZERO, 0, 1, ZERO, ZERO, 2, 3,
52 ZERO, ZERO, 4, 5, ZERO, ZERO, 6, 7
53 };
54
55
56 /* At even X values we want the first 4 shorts, and at odd X values we
57 * want the second 4 shorts.
58 */
59 qword bias = (qword) spu_splats((unsigned char) ((ix & 0x01) << 3));
60 qword bias_mask = si_fsmbi(0x3333);
61 qword sv = si_a(shuf_vec, si_and(bias_mask, bias));
62
63 *depth = si_shufb(*ptr, *ptr, sv);
64 *stencil = si_il(0);
65 break;
66 }
67
68
69 case PIPE_FORMAT_Z32_UNORM: {
70 qword *ptr = (qword *) &buffer->ui4[iy][ix];
71
72 *depth = *ptr;
73 *stencil = si_il(0);
74 break;
75 }
76
77
78 case PIPE_FORMAT_Z24S8_UNORM: {
79 qword *ptr = (qword *) &buffer->ui4[iy][ix];
80 qword mask = si_fsmbi(0xEEEE);
81
82 *depth = si_rotmai(si_and(*ptr, mask), -8);
83 *stencil = si_andc(*ptr, mask);
84 break;
85 }
86
87
88 case PIPE_FORMAT_S8Z24_UNORM: {
89 qword *ptr = (qword *) &buffer->ui4[iy][ix];
90
91 *depth = si_and(*ptr, si_fsmbi(0x7777));
92 *stencil = si_andi(si_roti(*ptr, 8), 0x0ff);
93 break;
94 }
95
96
97 default:
98 assert(0);
99 break;
100 }
101 }
102
103
104 static void
105 write_ds_quad(tile_t *buffer, unsigned x, unsigned y,
106 enum pipe_format depth_format,
107 qword depth, qword stencil)
108 {
109 const int ix = x / 2;
110 const int iy = y / 2;
111
112 (void) stencil;
113
114 switch (depth_format) {
115 case PIPE_FORMAT_Z16_UNORM: {
116 qword *ptr = (qword *) &buffer->us8[iy][ix / 2];
117
118 qword sv = ((ix & 0x01) == 0)
119 ? (qword) { 2, 3, 6, 7, 10, 11, 14, 15,
120 24, 25, 26, 27, 28, 29, 30, 31 }
121 : (qword) { 16, 17, 18, 19, 20 , 21, 22, 23,
122 2, 3, 6, 7, 10, 11, 14, 15 };
123 *ptr = si_shufb(depth, *ptr, sv);
124 break;
125 }
126
127
128 case PIPE_FORMAT_Z32_UNORM: {
129 qword *ptr = (qword *) &buffer->ui4[iy][ix];
130 *ptr = depth;
131 break;
132 }
133
134
135 case PIPE_FORMAT_Z24S8_UNORM: {
136 qword *ptr = (qword *) &buffer->ui4[iy][ix];
137 qword mask = si_fsmbi(0xEEEE);
138
139 depth = si_shli(depth, 8);
140 *ptr = si_selb(stencil, depth, mask);
141 break;
142 }
143
144
145 case PIPE_FORMAT_S8Z24_UNORM: {
146 qword *ptr = (qword *) &buffer->ui4[iy][ix];
147 qword mask = si_fsmbi(0x7777);
148
149 stencil = si_shli(stencil, 24);
150 *ptr = si_selb(stencil, depth, mask);
151 break;
152 }
153
154
155 default:
156 assert(0);
157 break;
158 }
159 }
160
161
162 qword
163 spu_do_depth_stencil(int x, int y,
164 qword frag_mask, qword frag_depth, qword frag_alpha,
165 qword facing)
166 {
167 struct spu_frag_test_results result;
168 qword pixel_depth;
169 qword pixel_stencil;
170
171 /* All of this preable code (everthing before the call to frag_test) should
172 * be generated on the PPU and upload to the SPU.
173 */
174 if (spu.read_depth || spu.read_stencil) {
175 read_ds_quad(&spu.ztile, x, y, spu.fb.depth_format,
176 &pixel_depth, &pixel_stencil);
177 }
178
179 switch (spu.fb.depth_format) {
180 case PIPE_FORMAT_Z16_UNORM:
181 frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0x0000ffffu)));
182 frag_depth = si_cfltu(frag_depth, 0);
183 break;
184 case PIPE_FORMAT_Z32_UNORM:
185 frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0xffffffffu)));
186 frag_depth = si_cfltu(frag_depth, 0);
187 break;
188 case PIPE_FORMAT_Z24S8_UNORM:
189 case PIPE_FORMAT_S8Z24_UNORM:
190 frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0x00ffffffu)));
191 frag_depth = si_cfltu(frag_depth, 0);
192 break;
193 default:
194 ASSERT(0);
195 break;
196 }
197
198 result = (*spu.frag_test)(frag_mask, pixel_depth, pixel_stencil,
199 frag_depth, frag_alpha, facing);
200
201
202 /* This code (everthing after the call to frag_test) should
203 * be generated on the PPU and upload to the SPU.
204 */
205 if (spu.read_depth || spu.read_stencil) {
206 write_ds_quad(&spu.ztile, x, y, spu.fb.depth_format,
207 result.depth, result.stencil);
208 }
209
210 return result.mask;
211 }