1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
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.
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"
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"
49 #include "tgsi/tgsi_transform.h"
51 #include "draw_context.h"
52 #include "draw_pipe.h"
55 /** Approx number of new tokens for instructions in pstip_transform_inst() */
56 #define NUM_NEW_TOKENS 53
60 * Subclass of pipe_shader_state to carry extra fragment shader info.
62 struct pstip_fragment_shader
64 struct pipe_shader_state state
;
72 * Subclass of draw_stage
76 struct draw_stage stage
;
79 struct pipe_resource
*texture
;
80 struct pipe_sampler_view
*sampler_view
;
82 uint num_sampler_views
;
85 * Currently bound state
87 struct pstip_fragment_shader
*fs
;
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
;
95 * Driver interface/override functions
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 *);
102 void (*driver_bind_sampler_states
)(struct pipe_context
*, unsigned,
103 unsigned, unsigned, void **);
105 void (*driver_set_sampler_views
)(struct pipe_context
*,
106 unsigned shader
, unsigned start
,
108 struct pipe_sampler_view
**);
110 void (*driver_set_polygon_stipple
)(struct pipe_context
*,
111 const struct pipe_poly_stipple
*);
113 struct pipe_context
*pipe
;
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.
122 generate_pstip_fs(struct pstip_stage
*pstip
)
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
;
131 wincoord_file
= screen
->get_param(screen
, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL
) ?
132 TGSI_FILE_SYSTEM_VALUE
: TGSI_FILE_INPUT
;
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
,
139 if (pstip_fs
.tokens
== NULL
)
142 assert(pstip
->fs
->sampler_unit
< PIPE_MAX_SAMPLERS
);
144 pstip
->fs
->pstip_fs
= pstip
->driver_create_fs_state(pipe
, &pstip_fs
);
146 FREE((void *)pstip_fs
.tokens
);
148 if (!pstip
->fs
->pstip_fs
)
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.
160 bind_pstip_fragment_shader(struct pstip_stage
*pstip
)
162 struct draw_context
*draw
= pstip
->stage
.draw
;
163 if (!pstip
->fs
->pstip_fs
&&
164 !generate_pstip_fs(pstip
))
167 draw
->suspend_flushing
= TRUE
;
168 pstip
->driver_bind_fs_state(pstip
->pipe
, pstip
->fs
->pstip_fs
);
169 draw
->suspend_flushing
= FALSE
;
174 static inline struct pstip_stage
*
175 pstip_stage( struct draw_stage
*stage
)
177 return (struct pstip_stage
*) stage
;
182 pstip_first_tri(struct draw_stage
*stage
, struct prim_header
*header
)
184 struct pstip_stage
*pstip
= pstip_stage(stage
);
185 struct pipe_context
*pipe
= pstip
->pipe
;
186 struct draw_context
*draw
= stage
->draw
;
188 uint num_sampler_views
;
190 assert(stage
->draw
->rasterizer
->poly_stipple_enable
);
192 /* bind our fragprog */
193 if (!bind_pstip_fragment_shader(pstip
)) {
194 stage
->tri
= draw_pipe_passthrough_tri
;
195 stage
->tri(stage
, header
);
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
);
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
);
210 assert(num_samplers
<= PIPE_MAX_SAMPLERS
);
212 draw
->suspend_flushing
= TRUE
;
214 pstip
->driver_bind_sampler_states(pipe
, PIPE_SHADER_FRAGMENT
, 0,
215 num_samplers
, pstip
->state
.samplers
);
217 pstip
->driver_set_sampler_views(pipe
, PIPE_SHADER_FRAGMENT
, 0,
218 num_sampler_views
, pstip
->state
.sampler_views
);
220 draw
->suspend_flushing
= FALSE
;
222 /* now really draw first triangle */
223 stage
->tri
= draw_pipe_passthrough_tri
;
224 stage
->tri(stage
, header
);
229 pstip_flush(struct draw_stage
*stage
, unsigned flags
)
231 struct draw_context
*draw
= stage
->draw
;
232 struct pstip_stage
*pstip
= pstip_stage(stage
);
233 struct pipe_context
*pipe
= pstip
->pipe
;
235 stage
->tri
= pstip_first_tri
;
236 stage
->next
->flush( stage
->next
, flags
);
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
);
242 pstip
->driver_bind_sampler_states(pipe
, PIPE_SHADER_FRAGMENT
, 0,
244 pstip
->state
.samplers
);
246 pstip
->driver_set_sampler_views(pipe
, PIPE_SHADER_FRAGMENT
, 0,
247 pstip
->num_sampler_views
,
248 pstip
->state
.sampler_views
);
250 draw
->suspend_flushing
= FALSE
;
255 pstip_reset_stipple_counter(struct draw_stage
*stage
)
257 stage
->next
->reset_stipple_counter( stage
->next
);
262 pstip_destroy(struct draw_stage
*stage
)
264 struct pstip_stage
*pstip
= pstip_stage(stage
);
267 for (i
= 0; i
< PIPE_MAX_SHADER_SAMPLER_VIEWS
; i
++) {
268 pipe_sampler_view_reference(&pstip
->state
.sampler_views
[i
], NULL
);
271 pstip
->pipe
->delete_sampler_state(pstip
->pipe
, pstip
->sampler_cso
);
273 pipe_resource_reference(&pstip
->texture
, NULL
);
275 if (pstip
->sampler_view
) {
276 pipe_sampler_view_reference(&pstip
->sampler_view
, NULL
);
279 draw_free_temp_verts( stage
);
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
)
288 struct pstip_stage
*pstip
= CALLOC_STRUCT(pstip_stage
);
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
;
304 if (!draw_alloc_temp_verts( &pstip
->stage
, 8 ))
311 pstip
->stage
.destroy( &pstip
->stage
);
317 static struct pstip_stage
*
318 pstip_stage_from_pipe(struct pipe_context
*pipe
)
320 struct draw_context
*draw
= (struct draw_context
*) pipe
->draw
;
321 return pstip_stage(draw
->pipeline
.pstipple
);
326 * This function overrides the driver's create_fs_state() function and
327 * will typically be called by the state tracker.
330 pstip_create_fs_state(struct pipe_context
*pipe
,
331 const struct pipe_shader_state
*fs
)
333 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
334 struct pstip_fragment_shader
*pstipfs
= CALLOC_STRUCT(pstip_fragment_shader
);
337 pstipfs
->state
.tokens
= tgsi_dup_tokens(fs
->tokens
);
340 pstipfs
->driver_fs
= pstip
->driver_create_fs_state(pstip
->pipe
, fs
);
348 pstip_bind_fs_state(struct pipe_context
*pipe
, void *fs
)
350 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
351 struct pstip_fragment_shader
*pstipfs
= (struct pstip_fragment_shader
*) fs
;
355 pstip
->driver_bind_fs_state(pstip
->pipe
,
356 (pstipfs
? pstipfs
->driver_fs
: NULL
));
361 pstip_delete_fs_state(struct pipe_context
*pipe
, void *fs
)
363 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
364 struct pstip_fragment_shader
*pstipfs
= (struct pstip_fragment_shader
*) fs
;
366 pstip
->driver_delete_fs_state(pstip
->pipe
, pstipfs
->driver_fs
);
368 if (pstipfs
->pstip_fs
)
369 pstip
->driver_delete_fs_state(pstip
->pipe
, pstipfs
->pstip_fs
);
371 FREE((void*)pstipfs
->state
.tokens
);
377 pstip_bind_sampler_states(struct pipe_context
*pipe
, unsigned shader
,
378 unsigned start
, unsigned num
, void **sampler
)
380 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
385 if (shader
== PIPE_SHADER_FRAGMENT
) {
387 memcpy(pstip
->state
.samplers
, sampler
, num
* sizeof(void *));
388 for (i
= num
; i
< PIPE_MAX_SAMPLERS
; i
++) {
389 pstip
->state
.samplers
[i
] = NULL
;
391 pstip
->num_samplers
= num
;
395 pstip
->driver_bind_sampler_states(pstip
->pipe
, shader
, start
, num
, sampler
);
400 pstip_set_sampler_views(struct pipe_context
*pipe
,
401 unsigned shader
, unsigned start
, unsigned num
,
402 struct pipe_sampler_view
**views
)
404 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
407 if (shader
== PIPE_SHADER_FRAGMENT
) {
409 for (i
= 0; i
< num
; i
++) {
410 pipe_sampler_view_reference(&pstip
->state
.sampler_views
[start
+ i
],
413 pstip
->num_sampler_views
= num
;
417 pstip
->driver_set_sampler_views(pstip
->pipe
, shader
, start
, num
, views
);
422 pstip_set_polygon_stipple(struct pipe_context
*pipe
,
423 const struct pipe_poly_stipple
*stipple
)
425 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
428 pstip
->state
.stipple
= stipple
;
431 pstip
->driver_set_polygon_stipple(pstip
->pipe
, stipple
);
433 util_pstipple_update_stipple_texture(pstip
->pipe
, pstip
->texture
,
434 pstip
->state
.stipple
->stipple
);
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.
444 draw_install_pstipple_stage(struct draw_context
*draw
,
445 struct pipe_context
*pipe
)
447 struct pstip_stage
*pstip
;
449 pipe
->draw
= (void *) draw
;
452 * Create / install pgon stipple drawing / prim stage
454 pstip
= draw_pstip_stage( draw
, pipe
);
458 draw
->pipeline
.pstipple
= &pstip
->stage
;
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
;
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
;
469 /* create special texture, sampler state */
470 pstip
->texture
= util_pstipple_create_stipple_texture(pipe
, NULL
);
474 pstip
->sampler_view
= util_pstipple_create_sampler_view(pipe
,
476 if (!pstip
->sampler_view
)
479 pstip
->sampler_cso
= util_pstipple_create_sampler(pipe
);
480 if (!pstip
->sampler_cso
)
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
;
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
;
496 pstip
->stage
.destroy( &pstip
->stage
);