util: Move gallium's PIPE_FORMAT utils to /util/format/
[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/format/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 *,
103 enum pipe_shader_type,
104 unsigned, unsigned, void **);
105
106 void (*driver_set_sampler_views)(struct pipe_context *,
107 enum pipe_shader_type shader,
108 unsigned start, unsigned count,
109 struct pipe_sampler_view **);
110
111 void (*driver_set_polygon_stipple)(struct pipe_context *,
112 const struct pipe_poly_stipple *);
113
114 struct pipe_context *pipe;
115 };
116
117
118 /**
119 * Generate the frag shader we'll use for doing polygon stipple.
120 * This will be the user's shader prefixed with a TEX and KIL instruction.
121 */
122 static boolean
123 generate_pstip_fs(struct pstip_stage *pstip)
124 {
125 struct pipe_context *pipe = pstip->pipe;
126 struct pipe_screen *screen = pipe->screen;
127 const struct pipe_shader_state *orig_fs = &pstip->fs->state;
128 /*struct draw_context *draw = pstip->stage.draw;*/
129 struct pipe_shader_state pstip_fs;
130 enum tgsi_file_type wincoord_file;
131
132 wincoord_file = screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL) ?
133 TGSI_FILE_SYSTEM_VALUE : TGSI_FILE_INPUT;
134
135 pstip_fs = *orig_fs; /* copy to init */
136 pstip_fs.tokens = util_pstipple_create_fragment_shader(orig_fs->tokens,
137 &pstip->fs->sampler_unit,
138 0,
139 wincoord_file);
140 if (pstip_fs.tokens == NULL)
141 return FALSE;
142
143 assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
144
145 pstip->fs->pstip_fs = pstip->driver_create_fs_state(pipe, &pstip_fs);
146
147 FREE((void *)pstip_fs.tokens);
148
149 if (!pstip->fs->pstip_fs)
150 return FALSE;
151
152 return TRUE;
153 }
154
155
156 /**
157 * When we're about to draw our first stipple polygon in a batch, this function
158 * is called to tell the driver to bind our modified fragment shader.
159 */
160 static boolean
161 bind_pstip_fragment_shader(struct pstip_stage *pstip)
162 {
163 struct draw_context *draw = pstip->stage.draw;
164 if (!pstip->fs->pstip_fs &&
165 !generate_pstip_fs(pstip))
166 return FALSE;
167
168 draw->suspend_flushing = TRUE;
169 pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
170 draw->suspend_flushing = FALSE;
171 return TRUE;
172 }
173
174
175 static inline struct pstip_stage *
176 pstip_stage( struct draw_stage *stage )
177 {
178 return (struct pstip_stage *) stage;
179 }
180
181
182 static void
183 pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
184 {
185 struct pstip_stage *pstip = pstip_stage(stage);
186 struct pipe_context *pipe = pstip->pipe;
187 struct draw_context *draw = stage->draw;
188 uint num_samplers;
189 uint num_sampler_views;
190
191 assert(stage->draw->rasterizer->poly_stipple_enable);
192
193 /* bind our fragprog */
194 if (!bind_pstip_fragment_shader(pstip)) {
195 stage->tri = draw_pipe_passthrough_tri;
196 stage->tri(stage, header);
197 return;
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,
378 enum pipe_shader_type shader,
379 unsigned start, unsigned num, void **sampler)
380 {
381 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
382 uint i;
383
384 assert(start == 0);
385
386 if (shader == PIPE_SHADER_FRAGMENT) {
387 /* save current */
388 memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
389 for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
390 pstip->state.samplers[i] = NULL;
391 }
392 pstip->num_samplers = num;
393 }
394
395 /* pass-through */
396 pstip->driver_bind_sampler_states(pstip->pipe, shader, start, num, sampler);
397 }
398
399
400 static void
401 pstip_set_sampler_views(struct pipe_context *pipe,
402 enum pipe_shader_type shader,
403 unsigned start, unsigned num,
404 struct pipe_sampler_view **views)
405 {
406 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
407 uint i;
408
409 if (shader == PIPE_SHADER_FRAGMENT) {
410 /* save current */
411 for (i = 0; i < num; i++) {
412 pipe_sampler_view_reference(&pstip->state.sampler_views[start + i],
413 views[i]);
414 }
415 pstip->num_sampler_views = num;
416 }
417
418 /* pass-through */
419 pstip->driver_set_sampler_views(pstip->pipe, shader, start, num, views);
420 }
421
422
423 static void
424 pstip_set_polygon_stipple(struct pipe_context *pipe,
425 const struct pipe_poly_stipple *stipple)
426 {
427 struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
428
429 /* save current */
430 pstip->state.stipple = stipple;
431
432 /* pass-through */
433 pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
434
435 util_pstipple_update_stipple_texture(pstip->pipe, pstip->texture,
436 pstip->state.stipple->stipple);
437 }
438
439
440 /**
441 * Called by drivers that want to install this polygon stipple stage
442 * into the draw module's pipeline. This will not be used if the
443 * hardware has native support for polygon stipple.
444 */
445 boolean
446 draw_install_pstipple_stage(struct draw_context *draw,
447 struct pipe_context *pipe)
448 {
449 struct pstip_stage *pstip;
450
451 pipe->draw = (void *) draw;
452
453 /*
454 * Create / install pgon stipple drawing / prim stage
455 */
456 pstip = draw_pstip_stage( draw, pipe );
457 if (!pstip)
458 goto fail;
459
460 draw->pipeline.pstipple = &pstip->stage;
461
462 /* save original driver functions */
463 pstip->driver_create_fs_state = pipe->create_fs_state;
464 pstip->driver_bind_fs_state = pipe->bind_fs_state;
465 pstip->driver_delete_fs_state = pipe->delete_fs_state;
466
467 pstip->driver_bind_sampler_states = pipe->bind_sampler_states;
468 pstip->driver_set_sampler_views = pipe->set_sampler_views;
469 pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
470
471 /* create special texture, sampler state */
472 pstip->texture = util_pstipple_create_stipple_texture(pipe, NULL);
473 if (!pstip->texture)
474 goto fail;
475
476 pstip->sampler_view = util_pstipple_create_sampler_view(pipe,
477 pstip->texture);
478 if (!pstip->sampler_view)
479 goto fail;
480
481 pstip->sampler_cso = util_pstipple_create_sampler(pipe);
482 if (!pstip->sampler_cso)
483 goto fail;
484
485 /* override the driver's functions */
486 pipe->create_fs_state = pstip_create_fs_state;
487 pipe->bind_fs_state = pstip_bind_fs_state;
488 pipe->delete_fs_state = pstip_delete_fs_state;
489
490 pipe->bind_sampler_states = pstip_bind_sampler_states;
491 pipe->set_sampler_views = pstip_set_sampler_views;
492 pipe->set_polygon_stipple = pstip_set_polygon_stipple;
493
494 return TRUE;
495
496 fail:
497 if (pstip)
498 pstip->stage.destroy( &pstip->stage );
499
500 return FALSE;
501 }