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 *,
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
generate_pstip_fs(struct pstip_stage * pstip)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
bind_pstip_fragment_shader(struct pstip_stage * pstip)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 *
pstip_stage(struct draw_stage * stage)176 pstip_stage( struct draw_stage *stage )
177 {
178    return (struct pstip_stage *) stage;
179 }
180 
181 
182 static void
pstip_first_tri(struct draw_stage * stage,struct prim_header * header)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
pstip_flush(struct draw_stage * stage,unsigned flags)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
pstip_reset_stipple_counter(struct draw_stage * stage)255 pstip_reset_stipple_counter(struct draw_stage *stage)
256 {
257    stage->next->reset_stipple_counter( stage->next );
258 }
259 
260 
261 static void
pstip_destroy(struct draw_stage * stage)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 *
draw_pstip_stage(struct draw_context * draw,struct pipe_context * pipe)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 *
pstip_stage_from_pipe(struct pipe_context * pipe)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 *
pstip_create_fs_state(struct pipe_context * pipe,const struct pipe_shader_state * fs)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
pstip_bind_fs_state(struct pipe_context * pipe,void * fs)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
pstip_delete_fs_state(struct pipe_context * pipe,void * fs)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
pstip_bind_sampler_states(struct pipe_context * pipe,enum pipe_shader_type shader,unsigned start,unsigned num,void ** sampler)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
pstip_set_sampler_views(struct pipe_context * pipe,enum pipe_shader_type shader,unsigned start,unsigned num,struct pipe_sampler_view ** views)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
pstip_set_polygon_stipple(struct pipe_context * pipe,const struct pipe_poly_stipple * stipple)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
draw_install_pstipple_stage(struct draw_context * draw,struct pipe_context * pipe)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 }
502