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/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"
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
*,
103 enum pipe_shader_type
,
104 unsigned, unsigned, void **);
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
**);
111 void (*driver_set_polygon_stipple
)(struct pipe_context
*,
112 const struct pipe_poly_stipple
*);
114 struct pipe_context
*pipe
;
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.
123 generate_pstip_fs(struct pstip_stage
*pstip
)
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
;
132 wincoord_file
= screen
->get_param(screen
, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL
) ?
133 TGSI_FILE_SYSTEM_VALUE
: TGSI_FILE_INPUT
;
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
,
140 if (pstip_fs
.tokens
== NULL
)
143 assert(pstip
->fs
->sampler_unit
< PIPE_MAX_SAMPLERS
);
145 pstip
->fs
->pstip_fs
= pstip
->driver_create_fs_state(pipe
, &pstip_fs
);
147 FREE((void *)pstip_fs
.tokens
);
149 if (!pstip
->fs
->pstip_fs
)
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.
161 bind_pstip_fragment_shader(struct pstip_stage
*pstip
)
163 struct draw_context
*draw
= pstip
->stage
.draw
;
164 if (!pstip
->fs
->pstip_fs
&&
165 !generate_pstip_fs(pstip
))
168 draw
->suspend_flushing
= TRUE
;
169 pstip
->driver_bind_fs_state(pstip
->pipe
, pstip
->fs
->pstip_fs
);
170 draw
->suspend_flushing
= FALSE
;
175 static inline struct pstip_stage
*
176 pstip_stage( struct draw_stage
*stage
)
178 return (struct pstip_stage
*) stage
;
183 pstip_first_tri(struct draw_stage
*stage
, struct prim_header
*header
)
185 struct pstip_stage
*pstip
= pstip_stage(stage
);
186 struct pipe_context
*pipe
= pstip
->pipe
;
187 struct draw_context
*draw
= stage
->draw
;
189 uint num_sampler_views
;
191 assert(stage
->draw
->rasterizer
->poly_stipple_enable
);
193 /* bind our fragprog */
194 if (!bind_pstip_fragment_shader(pstip
)) {
195 stage
->tri
= draw_pipe_passthrough_tri
;
196 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
,
378 enum pipe_shader_type shader
,
379 unsigned start
, unsigned num
, void **sampler
)
381 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
386 if (shader
== PIPE_SHADER_FRAGMENT
) {
388 memcpy(pstip
->state
.samplers
, sampler
, num
* sizeof(void *));
389 for (i
= num
; i
< PIPE_MAX_SAMPLERS
; i
++) {
390 pstip
->state
.samplers
[i
] = NULL
;
392 pstip
->num_samplers
= num
;
396 pstip
->driver_bind_sampler_states(pstip
->pipe
, shader
, start
, num
, sampler
);
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
)
406 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
409 if (shader
== PIPE_SHADER_FRAGMENT
) {
411 for (i
= 0; i
< num
; i
++) {
412 pipe_sampler_view_reference(&pstip
->state
.sampler_views
[start
+ i
],
415 pstip
->num_sampler_views
= num
;
419 pstip
->driver_set_sampler_views(pstip
->pipe
, shader
, start
, num
, views
);
424 pstip_set_polygon_stipple(struct pipe_context
*pipe
,
425 const struct pipe_poly_stipple
*stipple
)
427 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
430 pstip
->state
.stipple
= stipple
;
433 pstip
->driver_set_polygon_stipple(pstip
->pipe
, stipple
);
435 util_pstipple_update_stipple_texture(pstip
->pipe
, pstip
->texture
,
436 pstip
->state
.stipple
->stipple
);
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.
446 draw_install_pstipple_stage(struct draw_context
*draw
,
447 struct pipe_context
*pipe
)
449 struct pstip_stage
*pstip
;
451 pipe
->draw
= (void *) draw
;
454 * Create / install pgon stipple drawing / prim stage
456 pstip
= draw_pstip_stage( draw
, pipe
);
460 draw
->pipeline
.pstipple
= &pstip
->stage
;
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
;
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
;
471 /* create special texture, sampler state */
472 pstip
->texture
= util_pstipple_create_stipple_texture(pipe
, NULL
);
476 pstip
->sampler_view
= util_pstipple_create_sampler_view(pipe
,
478 if (!pstip
->sampler_view
)
481 pstip
->sampler_cso
= util_pstipple_create_sampler(pipe
);
482 if (!pstip
->sampler_cso
)
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
;
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
;
498 pstip
->stage
.destroy( &pstip
->stage
);