695ddc089a46f7f8c70d298c0a185a3be2baedb9
[mesa.git] / src / gallium / drivers / llvmpipe / lp_rast.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "util/u_memory.h"
29
30 #include "lp_state.h"
31 #include "lp_rast.h"
32 #include "lp_rast_priv.h"
33 #include "lp_tile_soa.h"
34 #include "lp_bld_debug.h"
35
36
37 struct lp_rasterizer *lp_rast_create( void )
38 {
39 struct lp_rasterizer *rast;
40
41 rast = CALLOC_STRUCT(lp_rasterizer);
42 if(!rast)
43 return NULL;
44
45 rast->tile.color = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
46 rast->tile.depth = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
47
48 return rast;
49 }
50
51 void lp_rast_bind_color( struct lp_rasterizer *rast,
52 struct pipe_surface *cbuf,
53 boolean write_color )
54 {
55 pipe_surface_reference(&rast->state.cbuf, cbuf);
56 }
57
58 void lp_rast_bind_zstencil( struct lp_rasterizer *rast,
59 struct pipe_surface *zsbuf,
60 boolean write_zstencil )
61 {
62 pipe_surface_reference(&rast->state.zsbuf, zsbuf);
63 }
64
65
66 /* Begining of each tile:
67 */
68 void lp_rast_start_tile( struct lp_rasterizer *rast,
69 unsigned x,
70 unsigned y )
71 {
72 rast->x = x;
73 rast->y = y;
74 }
75
76 void lp_rast_clear_color( struct lp_rasterizer *rast,
77 const union lp_rast_cmd_arg *arg )
78 {
79 const uint8_t *clear_color = arg->clear_color;
80
81 if (clear_color[0] == clear_color[1] &&
82 clear_color[1] == clear_color[2] &&
83 clear_color[2] == clear_color[3]) {
84 memset(rast->tile.color, clear_color[0], TILE_SIZE * TILE_SIZE * 4);
85 }
86 else {
87 unsigned x, y, chan;
88 for (y = 0; y < TILE_SIZE; y++)
89 for (x = 0; x < TILE_SIZE; x++)
90 for (chan = 0; chan < 4; ++chan)
91 TILE_PIXEL(rast->tile.color, x, y, chan) = clear_color[chan];
92 }
93 }
94
95 void lp_rast_clear_zstencil( struct lp_rasterizer *rast,
96 const union lp_rast_cmd_arg *arg)
97 {
98 const unsigned clear_zstencil = arg->clear_zstencil;
99 unsigned i, j;
100
101 for (i = 0; i < TILE_SIZE; i++)
102 for (j = 0; j < TILE_SIZE; j++)
103 rast->tile.depth[i*TILE_SIZE + j] = clear_zstencil;
104 }
105
106
107 void lp_rast_load_color( struct lp_rasterizer *rast,
108 const union lp_rast_cmd_arg *arg)
109 {
110 /* call u_tile func to load colors from surface */
111 }
112
113 void lp_rast_load_zstencil( struct lp_rasterizer *rast,
114 const union lp_rast_cmd_arg *arg )
115 {
116 /* call u_tile func to load depth (and stencil?) from surface */
117 }
118
119 /* Within a tile:
120 */
121 void lp_rast_set_state( struct lp_rasterizer *rast,
122 const union lp_rast_cmd_arg *arg )
123 {
124 rast->shader_state = arg->set_state;
125
126 }
127
128
129 void lp_rast_shade_tile( struct lp_rasterizer *rast,
130 const union lp_rast_cmd_arg *arg,
131 const struct lp_rast_shader_inputs *inputs )
132 {
133 const unsigned masks[4] = {~0, ~0, ~0, ~0};
134 unsigned x, y;
135
136 /* Use the existing preference for 8x2 (four quads) shading:
137 */
138 for (y = 0; y < TILE_SIZE; y += 2)
139 for (x = 0; x < TILE_SIZE; x += 8)
140 lp_rast_shade_quads( rast, inputs, x, y, masks);
141 }
142
143
144 void lp_rast_shade_quads( struct lp_rasterizer *rast,
145 const struct lp_rast_shader_inputs *inputs,
146 unsigned x, unsigned y,
147 const unsigned *masks)
148 {
149 const struct lp_rast_state *state = rast->shader_state;
150 struct lp_rast_tile *tile = &rast->tile;
151 void *color;
152 void *depth;
153 uint32_t ALIGN16_ATTRIB mask[4][NUM_CHANNELS];
154 unsigned chan_index;
155 unsigned q;
156
157 /* Sanity checks */
158 assert(x % TILE_VECTOR_WIDTH == 0);
159 assert(y % TILE_VECTOR_HEIGHT == 0);
160
161 /* mask */
162 for (q = 0; q < 4; ++q)
163 for (chan_index = 0; chan_index < NUM_CHANNELS; ++chan_index)
164 mask[q][chan_index] = masks[q] & (1 << chan_index) ? ~0 : 0;
165
166 /* color buffer */
167 color = &TILE_PIXEL(tile->color, x, y, 0);
168
169 /* depth buffer */
170 assert((x % 2) == 0);
171 assert((y % 2) == 0);
172 depth = tile->depth + y*TILE_SIZE + 2*x;
173
174 /* XXX: This will most likely fail on 32bit x86 without -mstackrealign */
175 assert(lp_check_alignment(mask, 16));
176
177 assert(lp_check_alignment(depth, 16));
178 assert(lp_check_alignment(color, 16));
179 assert(lp_check_alignment(state->jc.blend_color, 16));
180
181 /* run shader */
182 state->shader( &state->jc,
183 x, y,
184 inputs->a0,
185 inputs->dadx,
186 inputs->dady,
187 &mask[0][0],
188 color,
189 depth);
190
191 }
192
193
194 /* End of tile:
195 */
196
197
198 void lp_rast_end_tile( struct lp_rasterizer *rast,
199 boolean write_depth )
200 {
201 struct pipe_surface *surface;
202 struct pipe_screen *screen;
203 struct pipe_transfer *transfer;
204 const unsigned x = rast->x;
205 const unsigned y = rast->y;
206 unsigned w = TILE_SIZE;
207 unsigned h = TILE_SIZE;
208 void *map;
209
210 surface = rast->state.cbuf;
211 if(!surface)
212 return;
213
214 screen = surface->texture->screen;
215
216 if(x + w > surface->width)
217 w = surface->width - x;
218 if(y + h > surface->height)
219 h = surface->height - y;
220
221 transfer = screen->get_tex_transfer(screen,
222 surface->texture,
223 surface->face,
224 surface->level,
225 surface->zslice,
226 PIPE_TRANSFER_READ_WRITE,
227 x, y, w, h);
228 if(!transfer)
229 return;
230
231 map = screen->transfer_map(screen, transfer);
232 if(map) {
233 lp_tile_write_4ub(transfer->format,
234 rast->tile.color,
235 map, transfer->stride,
236 x, y, w, h);
237
238 screen->transfer_unmap(screen, transfer);
239 }
240
241 screen->tex_transfer_destroy(transfer);
242
243 if (write_depth) {
244 /* FIXME: call u_tile func to store depth/stencil to surface */
245 }
246 }
247
248 /* Shutdown:
249 */
250 void lp_rast_destroy( struct lp_rasterizer *rast )
251 {
252 pipe_surface_reference(&rast->state.cbuf, NULL);
253 pipe_surface_reference(&rast->state.zsbuf, NULL);
254 align_free(rast->tile.depth);
255 align_free(rast->tile.color);
256 FREE(rast);
257 }
258