gallium/tgsi: pass TGSI tex target to tgsi_transform_tex_inst()
[mesa.git] / src / gallium / auxiliary / draw / draw_pipe_pstipple.c
1 /**************************************************************************
2 *
3 * Copyright 2008 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 /**
29 * Polygon stipple stage: implement polygon stipple with texture map and
30 * fragment program. The fragment program samples the texture using the
31 * fragment window coordinate register and does a fragment kill for the
32 * stipple-failing fragments.
33 *
34 * Authors: Brian Paul
35 */
36
37
38 #include "pipe/p_context.h"
39 #include "pipe/p_defines.h"
40 #include "pipe/p_shader_tokens.h"
41 #include "util/u_inlines.h"
42
43 #include "util/u_format.h"
44 #include "util/u_math.h"
45 #include "util/u_memory.h"
46 #include "util/u_pstipple.h"
47 #include "util/u_sampler.h"
48
49 #include "tgsi/tgsi_transform.h"
50
51 #include "draw_context.h"
52 #include "draw_pipe.h"
53
54
55 /** Approx number of new tokens for instructions in pstip_transform_inst() */
56 #define NUM_NEW_TOKENS 53
57
58
59 /**
60 * Subclass of pipe_shader_state to carry extra fragment shader info.
61 */
62 struct pstip_fragment_shader
63 {
64 struct pipe_shader_state state;
65 void *driver_fs;
66 void *pstip_fs;
67 uint sampler_unit;
68 };
69
70
71 /**
72 * Subclass of draw_stage
73 */
74 struct pstip_stage
75 {
76 struct draw_stage stage;
77
78 void *sampler_cso;
79 struct pipe_resource *texture;
80 struct pipe_sampler_view *sampler_view;
81 uint num_samplers;
82 uint num_sampler_views;
83
84 /*
85 * Currently bound state
86 */
87 struct pstip_fragment_shader *fs;
88 struct {
89 void *samplers[PIPE_MAX_SAMPLERS];
90 struct pipe_sampler_view *sampler_views[PIPE_MAX_SHADER_SAMPLER_VIEWS];
91 const struct pipe_poly_stipple *stipple;
92 } state;
93
94 /*
95 * Driver interface/override functions
96 */
97 void * (*driver_create_fs_state)(struct pipe_context *,
98 const struct pipe_shader_state *);
99 void (*driver_bind_fs_state)(struct pipe_context *, void *);
100 void (*driver_delete_fs_state)(struct pipe_context *, void *);
101
102 void (*driver_bind_sampler_states)(struct pipe_context *, unsigned,
103 unsigned, unsigned, void **);
104
105 void (*driver_set_sampler_views)(struct pipe_context *,
106 unsigned shader, unsigned start,
107 unsigned count,
108 struct pipe_sampler_view **);
109
110 void (*driver_set_polygon_stipple)(struct pipe_context *,
111 const struct pipe_poly_stipple *);
112
113 struct pipe_context *pipe;
114 };
115
116
117 /**
118 * Generate the frag shader we'll use for doing polygon stipple.
119 * This will be the user's shader prefixed with a TEX and KIL instruction.
120 */
121 static boolean
122 generate_pstip_fs(struct pstip_stage *pstip)
123 {
124 struct pipe_context *pipe = pstip->pipe;
125 struct pipe_screen *screen = pipe->screen;
126 const struct pipe_shader_state *orig_fs = &pstip->fs->state;
127 /*struct draw_context *draw = pstip->stage.draw;*/
128 struct pipe_shader_state pstip_fs;
129 enum tgsi_file_type wincoord_file;
130
131 wincoord_file = screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL) ?
132 TGSI_FILE_SYSTEM_VALUE : TGSI_FILE_INPUT;
133
134 pstip_fs = *orig_fs; /* copy to init */
135 pstip_fs.tokens = util_pstipple_create_fragment_shader(orig_fs->tokens,
136 &pstip->fs->sampler_unit,
137 0,
138 wincoord_file);
139 if (pstip_fs.tokens == NULL)
140 return FALSE;
141
142 assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
143
144 pstip->fs->pstip_fs = pstip->driver_create_fs_state(pipe, &pstip_fs);
145
146 FREE((void *)pstip_fs.tokens);
147
148 if (!pstip->fs->pstip_fs)
149 return FALSE;
150
151 return TRUE;
152 }
153
154
155 /**
156 * When we're about to draw our first stipple polygon in a batch, this function
157 * is called to tell the driver to bind our modified fragment shader.
158 */
159 static boolean
160 bind_pstip_fragment_shader(struct pstip_stage *pstip)
161 {
162 struct draw_context *draw = pstip->stage.draw;
163 if (!pstip->fs->pstip_fs &&
164 !generate_pstip_fs(pstip))
165 return FALSE;
166
167 draw->suspend_flushing = TRUE;
168 pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
169 draw->suspend_flushing = FALSE;
170 return TRUE;
171 }
172
173
174 static inline struct pstip_stage *
175 pstip_stage( struct draw_stage *stage )
176 {
177 return (struct pstip_stage *) stage;
178 }
179
180
181 static void
182 pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
183 {
184 struct pstip_stage *pstip = pstip_stage(stage);
185 struct pipe_context *pipe = pstip->pipe;
186 struct draw_context *draw = stage->draw;
187 uint num_samplers;
188 uint num_sampler_views;
189
190 assert(stage->draw->rasterizer->poly_stipple_enable);
191
192 /* bind our fragprog */
193 if (!bind_pstip_fragment_shader(pstip)) {
194 stage->tri = draw_pipe_passthrough_tri;
195 stage->tri(stage, header);
196 return;
197 }
198
199
200 /* how many samplers? */
201 /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
202 num_samplers = MAX2(pstip->num_samplers, pstip->fs->sampler_unit + 1);
203 num_sampler_views = MAX2(pstip->num_sampler_views, num_samplers);
204
205 /* plug in our sampler, texture */
206 pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
207 pipe_sampler_view_reference(&pstip->state.sampler_views[pstip->fs->sampler_unit],
208 pstip->sampler_view);
209
210 assert(num_samplers <= PIPE_MAX_SAMPLERS);
211
212 draw->suspend_flushing = TRUE;
213
214 pstip->driver_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,
215 num_samplers, pstip->state.samplers);
216
217 pstip->driver_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
218 num_sampler_views, pstip->state.sampler_views);
219
220 draw->suspend_flushing = FALSE;
221
222 /* now really draw first triangle */
223 stage->tri = draw_pipe_passthrough_tri;
224 stage->tri(stage, header);
225 }
226
227
228 static void
229 pstip_flush(struct draw_stage *stage, unsigned flags)
230 {
231 struct draw_context *draw = stage->draw;
232 struct pstip_stage *pstip = pstip_stage(stage);
233 struct pipe_context *pipe = pstip->pipe;
234
235 stage->tri = pstip_first_tri;
236 stage->next->flush( stage->next, flags );
237
238 /* restore original frag shader, texture, sampler state */
239 draw->suspend_flushing = TRUE;
240 pstip->driver_bind_fs_state(pipe, pstip->fs ? pstip->fs->driver_fs : NULL);
241
242 pstip->driver_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,
243 pstip->num_samplers,
244 pstip->state.samplers);
245
246 pstip->driver_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
247 pstip->num_sampler_views,
248 pstip->state.sampler_views);
249
250 draw->suspend_flushing = FALSE;
251 }
252
253
254 static void
255 pstip_reset_stipple_counter(struct draw_stage *stage)
256 {
257 stage->next->reset_stipple_counter( stage->next );
258 }
259
260
261 static void
262 pstip_destroy(struct draw_stage *stage)
263 {
264 struct pstip_stage *pstip = pstip_stage(stage);
265 uint i;
266
267 for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
268 pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL);
269 }
270
271 pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso);
272
273 pipe_resource_reference(&pstip->texture, NULL);
274
275 if (pstip->sampler_view) {
276 pipe_sampler_view_reference(&pstip->sampler_view, NULL);
277 }
278
279 draw_free_temp_verts( stage );
280 FREE( stage );
281 }
282
283
284 /** Create a new polygon stipple drawing stage object */
285 static struct pstip_stage *
286 draw_pstip_stage(struct draw_context *draw, struct pipe_context *pipe)
287 {
288 struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
289 if (!pstip)
290 goto fail;
291
292 pstip->pipe = pipe;
293
294 pstip->stage.draw = draw;
295 pstip->stage.name = "pstip";
296 pstip->stage.next = NULL;
297 pstip->stage.point = draw_pipe_passthrough_point;
298 pstip->stage.line = draw_pipe_passthrough_line;
299 pstip->stage.tri = pstip_first_tri;
300 pstip->stage.flush = pstip_flush;
301 pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
302 pstip->stage.destroy = pstip_destroy;
303
304 if (!draw_alloc_temp_verts( &pstip->stage, 8 ))
305 goto fail;
306
307 return pstip;
308
309 fail:
310 if (pstip)
311 pstip->stage.destroy( &pstip->stage );
312
313 return NULL;
314 }
315
316
317 static struct pstip_stage *
318 pstip_stage_from_pipe(struct pipe_context *pipe)
319 {
320 struct draw_context *draw = (struct draw_context *) pipe->draw;
321 return pstip_stage(draw->pipeline.pstipple);
322 }
323
324
325 /**
326 * This function overrides the driver's create_fs_state() function and
327 * will typically be called by the state tracker.
328 */
329 static void *
330 pstip_create_fs_state(struct pipe_context *pipe,
331 const struct pipe_shader_state *fs)
332 {
333 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
334 struct pstip_fragment_shader *pstipfs = CALLOC_STRUCT(pstip_fragment_shader);
335
336 if (pstipfs) {
337 pstipfs->state.tokens = tgsi_dup_tokens(fs->tokens);
338
339 /* pass-through */
340 pstipfs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
341 }
342
343 return pstipfs;
344 }
345
346
347 static void
348 pstip_bind_fs_state(struct pipe_context *pipe, void *fs)
349 {
350 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
351 struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
352 /* save current */
353 pstip->fs = pstipfs;
354 /* pass-through */
355 pstip->driver_bind_fs_state(pstip->pipe,
356 (pstipfs ? pstipfs->driver_fs : NULL));
357 }
358
359
360 static void
361 pstip_delete_fs_state(struct pipe_context *pipe, void *fs)
362 {
363 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
364 struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
365 /* pass-through */
366 pstip->driver_delete_fs_state(pstip->pipe, pstipfs->driver_fs);
367
368 if (pstipfs->pstip_fs)
369 pstip->driver_delete_fs_state(pstip->pipe, pstipfs->pstip_fs);
370
371 FREE((void*)pstipfs->state.tokens);
372 FREE(pstipfs);
373 }
374
375
376 static void
377 pstip_bind_sampler_states(struct pipe_context *pipe, unsigned shader,
378 unsigned start, unsigned num, void **sampler)
379 {
380 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
381 uint i;
382
383 assert(start == 0);
384
385 if (shader == PIPE_SHADER_FRAGMENT) {
386 /* save current */
387 memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
388 for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
389 pstip->state.samplers[i] = NULL;
390 }
391 pstip->num_samplers = num;
392 }
393
394 /* pass-through */
395 pstip->driver_bind_sampler_states(pstip->pipe, shader, start, num, sampler);
396 }
397
398
399 static void
400 pstip_set_sampler_views(struct pipe_context *pipe,
401 unsigned shader, unsigned start, unsigned num,
402 struct pipe_sampler_view **views)
403 {
404 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
405 uint i;
406
407 if (shader == PIPE_SHADER_FRAGMENT) {
408 /* save current */
409 for (i = 0; i < num; i++) {
410 pipe_sampler_view_reference(&pstip->state.sampler_views[start + i],
411 views[i]);
412 }
413 pstip->num_sampler_views = num;
414 }
415
416 /* pass-through */
417 pstip->driver_set_sampler_views(pstip->pipe, shader, start, num, views);
418 }
419
420
421 static void
422 pstip_set_polygon_stipple(struct pipe_context *pipe,
423 const struct pipe_poly_stipple *stipple)
424 {
425 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
426
427 /* save current */
428 pstip->state.stipple = stipple;
429
430 /* pass-through */
431 pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
432
433 util_pstipple_update_stipple_texture(pstip->pipe, pstip->texture,
434 pstip->state.stipple->stipple);
435 }
436
437
438 /**
439 * Called by drivers that want to install this polygon stipple stage
440 * into the draw module's pipeline. This will not be used if the
441 * hardware has native support for polygon stipple.
442 */
443 boolean
444 draw_install_pstipple_stage(struct draw_context *draw,
445 struct pipe_context *pipe)
446 {
447 struct pstip_stage *pstip;
448
449 pipe->draw = (void *) draw;
450
451 /*
452 * Create / install pgon stipple drawing / prim stage
453 */
454 pstip = draw_pstip_stage( draw, pipe );
455 if (!pstip)
456 goto fail;
457
458 draw->pipeline.pstipple = &pstip->stage;
459
460 /* save original driver functions */
461 pstip->driver_create_fs_state = pipe->create_fs_state;
462 pstip->driver_bind_fs_state = pipe->bind_fs_state;
463 pstip->driver_delete_fs_state = pipe->delete_fs_state;
464
465 pstip->driver_bind_sampler_states = pipe->bind_sampler_states;
466 pstip->driver_set_sampler_views = pipe->set_sampler_views;
467 pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
468
469 /* create special texture, sampler state */
470 pstip->texture = util_pstipple_create_stipple_texture(pipe, NULL);
471 if (!pstip->texture)
472 goto fail;
473
474 pstip->sampler_view = util_pstipple_create_sampler_view(pipe,
475 pstip->texture);
476 if (!pstip->sampler_view)
477 goto fail;
478
479 pstip->sampler_cso = util_pstipple_create_sampler(pipe);
480 if (!pstip->sampler_cso)
481 goto fail;
482
483 /* override the driver's functions */
484 pipe->create_fs_state = pstip_create_fs_state;
485 pipe->bind_fs_state = pstip_bind_fs_state;
486 pipe->delete_fs_state = pstip_delete_fs_state;
487
488 pipe->bind_sampler_states = pstip_bind_sampler_states;
489 pipe->set_sampler_views = pstip_set_sampler_views;
490 pipe->set_polygon_stipple = pstip_set_polygon_stipple;
491
492 return TRUE;
493
494 fail:
495 if (pstip)
496 pstip->stage.destroy( &pstip->stage );
497
498 return FALSE;
499 }