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 #include "nir/nir_draw_helpers.h"
57 /** Approx number of new tokens for instructions in pstip_transform_inst() */
58 #define NUM_NEW_TOKENS 53
62 * Subclass of pipe_shader_state to carry extra fragment shader info.
64 struct pstip_fragment_shader
66 struct pipe_shader_state state
;
74 * Subclass of draw_stage
78 struct draw_stage stage
;
81 struct pipe_resource
*texture
;
82 struct pipe_sampler_view
*sampler_view
;
84 uint num_sampler_views
;
87 * Currently bound state
89 struct pstip_fragment_shader
*fs
;
91 void *samplers
[PIPE_MAX_SAMPLERS
];
92 struct pipe_sampler_view
*sampler_views
[PIPE_MAX_SHADER_SAMPLER_VIEWS
];
93 const struct pipe_poly_stipple
*stipple
;
97 * Driver interface/override functions
99 void * (*driver_create_fs_state
)(struct pipe_context
*,
100 const struct pipe_shader_state
*);
101 void (*driver_bind_fs_state
)(struct pipe_context
*, void *);
102 void (*driver_delete_fs_state
)(struct pipe_context
*, void *);
104 void (*driver_bind_sampler_states
)(struct pipe_context
*,
105 enum pipe_shader_type
,
106 unsigned, unsigned, void **);
108 void (*driver_set_sampler_views
)(struct pipe_context
*,
109 enum pipe_shader_type shader
,
110 unsigned start
, unsigned count
,
111 struct pipe_sampler_view
**);
113 void (*driver_set_polygon_stipple
)(struct pipe_context
*,
114 const struct pipe_poly_stipple
*);
116 struct pipe_context
*pipe
;
121 * Generate the frag shader we'll use for doing polygon stipple.
122 * This will be the user's shader prefixed with a TEX and KIL instruction.
125 generate_pstip_fs(struct pstip_stage
*pstip
)
127 struct pipe_context
*pipe
= pstip
->pipe
;
128 struct pipe_screen
*screen
= pipe
->screen
;
129 const struct pipe_shader_state
*orig_fs
= &pstip
->fs
->state
;
130 /*struct draw_context *draw = pstip->stage.draw;*/
131 struct pipe_shader_state pstip_fs
;
132 enum tgsi_file_type wincoord_file
;
134 wincoord_file
= screen
->get_param(screen
, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL
) ?
135 TGSI_FILE_SYSTEM_VALUE
: TGSI_FILE_INPUT
;
137 pstip_fs
= *orig_fs
; /* copy to init */
138 if (orig_fs
->type
== PIPE_SHADER_IR_TGSI
) {
139 pstip_fs
.tokens
= util_pstipple_create_fragment_shader(orig_fs
->tokens
,
140 &pstip
->fs
->sampler_unit
,
143 if (pstip_fs
.tokens
== NULL
)
146 #ifdef LLVM_AVAILABLE
147 pstip_fs
.ir
.nir
= nir_shader_clone(NULL
, orig_fs
->ir
.nir
);
148 nir_lower_pstipple_fs(pstip_fs
.ir
.nir
,
149 &pstip
->fs
->sampler_unit
, 0, wincoord_file
== TGSI_FILE_SYSTEM_VALUE
);
153 assert(pstip
->fs
->sampler_unit
< PIPE_MAX_SAMPLERS
);
155 pstip
->fs
->pstip_fs
= pstip
->driver_create_fs_state(pipe
, &pstip_fs
);
157 FREE((void *)pstip_fs
.tokens
);
159 if (!pstip
->fs
->pstip_fs
)
167 * When we're about to draw our first stipple polygon in a batch, this function
168 * is called to tell the driver to bind our modified fragment shader.
171 bind_pstip_fragment_shader(struct pstip_stage
*pstip
)
173 struct draw_context
*draw
= pstip
->stage
.draw
;
174 if (!pstip
->fs
->pstip_fs
&&
175 !generate_pstip_fs(pstip
))
178 draw
->suspend_flushing
= TRUE
;
179 pstip
->driver_bind_fs_state(pstip
->pipe
, pstip
->fs
->pstip_fs
);
180 draw
->suspend_flushing
= FALSE
;
185 static inline struct pstip_stage
*
186 pstip_stage( struct draw_stage
*stage
)
188 return (struct pstip_stage
*) stage
;
193 pstip_first_tri(struct draw_stage
*stage
, struct prim_header
*header
)
195 struct pstip_stage
*pstip
= pstip_stage(stage
);
196 struct pipe_context
*pipe
= pstip
->pipe
;
197 struct draw_context
*draw
= stage
->draw
;
199 uint num_sampler_views
;
201 assert(stage
->draw
->rasterizer
->poly_stipple_enable
);
203 /* bind our fragprog */
204 if (!bind_pstip_fragment_shader(pstip
)) {
205 stage
->tri
= draw_pipe_passthrough_tri
;
206 stage
->tri(stage
, header
);
210 /* how many samplers? */
211 /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
212 num_samplers
= MAX2(pstip
->num_samplers
, pstip
->fs
->sampler_unit
+ 1);
213 num_sampler_views
= MAX2(pstip
->num_sampler_views
, num_samplers
);
215 /* plug in our sampler, texture */
216 pstip
->state
.samplers
[pstip
->fs
->sampler_unit
] = pstip
->sampler_cso
;
217 pipe_sampler_view_reference(&pstip
->state
.sampler_views
[pstip
->fs
->sampler_unit
],
218 pstip
->sampler_view
);
220 assert(num_samplers
<= PIPE_MAX_SAMPLERS
);
222 draw
->suspend_flushing
= TRUE
;
224 pstip
->driver_bind_sampler_states(pipe
, PIPE_SHADER_FRAGMENT
, 0,
225 num_samplers
, pstip
->state
.samplers
);
227 pstip
->driver_set_sampler_views(pipe
, PIPE_SHADER_FRAGMENT
, 0,
228 num_sampler_views
, pstip
->state
.sampler_views
);
230 draw
->suspend_flushing
= FALSE
;
232 /* now really draw first triangle */
233 stage
->tri
= draw_pipe_passthrough_tri
;
234 stage
->tri(stage
, header
);
239 pstip_flush(struct draw_stage
*stage
, unsigned flags
)
241 struct draw_context
*draw
= stage
->draw
;
242 struct pstip_stage
*pstip
= pstip_stage(stage
);
243 struct pipe_context
*pipe
= pstip
->pipe
;
245 stage
->tri
= pstip_first_tri
;
246 stage
->next
->flush( stage
->next
, flags
);
248 /* restore original frag shader, texture, sampler state */
249 draw
->suspend_flushing
= TRUE
;
250 pstip
->driver_bind_fs_state(pipe
, pstip
->fs
? pstip
->fs
->driver_fs
: NULL
);
252 pstip
->driver_bind_sampler_states(pipe
, PIPE_SHADER_FRAGMENT
, 0,
254 pstip
->state
.samplers
);
256 pstip
->driver_set_sampler_views(pipe
, PIPE_SHADER_FRAGMENT
, 0,
257 pstip
->num_sampler_views
,
258 pstip
->state
.sampler_views
);
260 draw
->suspend_flushing
= FALSE
;
265 pstip_reset_stipple_counter(struct draw_stage
*stage
)
267 stage
->next
->reset_stipple_counter( stage
->next
);
272 pstip_destroy(struct draw_stage
*stage
)
274 struct pstip_stage
*pstip
= pstip_stage(stage
);
277 for (i
= 0; i
< PIPE_MAX_SHADER_SAMPLER_VIEWS
; i
++) {
278 pipe_sampler_view_reference(&pstip
->state
.sampler_views
[i
], NULL
);
281 pstip
->pipe
->delete_sampler_state(pstip
->pipe
, pstip
->sampler_cso
);
283 pipe_resource_reference(&pstip
->texture
, NULL
);
285 if (pstip
->sampler_view
) {
286 pipe_sampler_view_reference(&pstip
->sampler_view
, NULL
);
289 draw_free_temp_verts( stage
);
294 /** Create a new polygon stipple drawing stage object */
295 static struct pstip_stage
*
296 draw_pstip_stage(struct draw_context
*draw
, struct pipe_context
*pipe
)
298 struct pstip_stage
*pstip
= CALLOC_STRUCT(pstip_stage
);
304 pstip
->stage
.draw
= draw
;
305 pstip
->stage
.name
= "pstip";
306 pstip
->stage
.next
= NULL
;
307 pstip
->stage
.point
= draw_pipe_passthrough_point
;
308 pstip
->stage
.line
= draw_pipe_passthrough_line
;
309 pstip
->stage
.tri
= pstip_first_tri
;
310 pstip
->stage
.flush
= pstip_flush
;
311 pstip
->stage
.reset_stipple_counter
= pstip_reset_stipple_counter
;
312 pstip
->stage
.destroy
= pstip_destroy
;
314 if (!draw_alloc_temp_verts( &pstip
->stage
, 8 ))
321 pstip
->stage
.destroy( &pstip
->stage
);
327 static struct pstip_stage
*
328 pstip_stage_from_pipe(struct pipe_context
*pipe
)
330 struct draw_context
*draw
= (struct draw_context
*) pipe
->draw
;
331 return pstip_stage(draw
->pipeline
.pstipple
);
336 * This function overrides the driver's create_fs_state() function and
337 * will typically be called by the gallium frontend.
340 pstip_create_fs_state(struct pipe_context
*pipe
,
341 const struct pipe_shader_state
*fs
)
343 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
344 struct pstip_fragment_shader
*pstipfs
= CALLOC_STRUCT(pstip_fragment_shader
);
347 pstipfs
->state
.type
= fs
->type
;
348 if (fs
->type
== PIPE_SHADER_IR_TGSI
)
349 pstipfs
->state
.tokens
= tgsi_dup_tokens(fs
->tokens
);
351 pstipfs
->state
.ir
.nir
= nir_shader_clone(NULL
, fs
->ir
.nir
);
354 pstipfs
->driver_fs
= pstip
->driver_create_fs_state(pstip
->pipe
, fs
);
362 pstip_bind_fs_state(struct pipe_context
*pipe
, void *fs
)
364 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
365 struct pstip_fragment_shader
*pstipfs
= (struct pstip_fragment_shader
*) fs
;
369 pstip
->driver_bind_fs_state(pstip
->pipe
,
370 (pstipfs
? pstipfs
->driver_fs
: NULL
));
375 pstip_delete_fs_state(struct pipe_context
*pipe
, void *fs
)
377 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
378 struct pstip_fragment_shader
*pstipfs
= (struct pstip_fragment_shader
*) fs
;
380 pstip
->driver_delete_fs_state(pstip
->pipe
, pstipfs
->driver_fs
);
382 if (pstipfs
->pstip_fs
)
383 pstip
->driver_delete_fs_state(pstip
->pipe
, pstipfs
->pstip_fs
);
385 if (pstipfs
->state
.type
== PIPE_SHADER_IR_TGSI
)
386 FREE((void*)pstipfs
->state
.tokens
);
388 ralloc_free(pstipfs
->state
.ir
.nir
);
394 pstip_bind_sampler_states(struct pipe_context
*pipe
,
395 enum pipe_shader_type shader
,
396 unsigned start
, unsigned num
, void **sampler
)
398 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
403 if (shader
== PIPE_SHADER_FRAGMENT
) {
405 memcpy(pstip
->state
.samplers
, sampler
, num
* sizeof(void *));
406 for (i
= num
; i
< PIPE_MAX_SAMPLERS
; i
++) {
407 pstip
->state
.samplers
[i
] = NULL
;
409 pstip
->num_samplers
= num
;
413 pstip
->driver_bind_sampler_states(pstip
->pipe
, shader
, start
, num
, sampler
);
418 pstip_set_sampler_views(struct pipe_context
*pipe
,
419 enum pipe_shader_type shader
,
420 unsigned start
, unsigned num
,
421 struct pipe_sampler_view
**views
)
423 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
426 if (shader
== PIPE_SHADER_FRAGMENT
) {
428 for (i
= 0; i
< num
; i
++) {
429 pipe_sampler_view_reference(&pstip
->state
.sampler_views
[start
+ i
],
432 pstip
->num_sampler_views
= num
;
436 pstip
->driver_set_sampler_views(pstip
->pipe
, shader
, start
, num
, views
);
441 pstip_set_polygon_stipple(struct pipe_context
*pipe
,
442 const struct pipe_poly_stipple
*stipple
)
444 struct pstip_stage
*pstip
= pstip_stage_from_pipe(pipe
);
447 pstip
->state
.stipple
= stipple
;
450 pstip
->driver_set_polygon_stipple(pstip
->pipe
, stipple
);
452 util_pstipple_update_stipple_texture(pstip
->pipe
, pstip
->texture
,
453 pstip
->state
.stipple
->stipple
);
458 * Called by drivers that want to install this polygon stipple stage
459 * into the draw module's pipeline. This will not be used if the
460 * hardware has native support for polygon stipple.
463 draw_install_pstipple_stage(struct draw_context
*draw
,
464 struct pipe_context
*pipe
)
466 struct pstip_stage
*pstip
;
468 pipe
->draw
= (void *) draw
;
471 * Create / install pgon stipple drawing / prim stage
473 pstip
= draw_pstip_stage( draw
, pipe
);
477 draw
->pipeline
.pstipple
= &pstip
->stage
;
479 /* save original driver functions */
480 pstip
->driver_create_fs_state
= pipe
->create_fs_state
;
481 pstip
->driver_bind_fs_state
= pipe
->bind_fs_state
;
482 pstip
->driver_delete_fs_state
= pipe
->delete_fs_state
;
484 pstip
->driver_bind_sampler_states
= pipe
->bind_sampler_states
;
485 pstip
->driver_set_sampler_views
= pipe
->set_sampler_views
;
486 pstip
->driver_set_polygon_stipple
= pipe
->set_polygon_stipple
;
488 /* create special texture, sampler state */
489 pstip
->texture
= util_pstipple_create_stipple_texture(pipe
, NULL
);
493 pstip
->sampler_view
= util_pstipple_create_sampler_view(pipe
,
495 if (!pstip
->sampler_view
)
498 pstip
->sampler_cso
= util_pstipple_create_sampler(pipe
);
499 if (!pstip
->sampler_cso
)
502 /* override the driver's functions */
503 pipe
->create_fs_state
= pstip_create_fs_state
;
504 pipe
->bind_fs_state
= pstip_bind_fs_state
;
505 pipe
->delete_fs_state
= pstip_delete_fs_state
;
507 pipe
->bind_sampler_states
= pstip_bind_sampler_states
;
508 pipe
->set_sampler_views
= pstip_set_sampler_views
;
509 pipe
->set_polygon_stipple
= pstip_set_polygon_stipple
;
515 pstip
->stage
.destroy( &pstip
->stage
);