Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch_shade_pipeline.c
1 /**************************************************************************
2  *
3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 #include "util/u_math.h"
29 #include "util/u_memory.h"
30 #include "util/u_prim.h"
31 #include "draw/draw_context.h"
32 #include "draw/draw_vbuf.h"
33 #include "draw/draw_vertex.h"
34 #include "draw/draw_pt.h"
35 #include "draw/draw_vs.h"
36 #include "draw/draw_gs.h"
37
38
39 struct fetch_pipeline_middle_end {
40    struct draw_pt_middle_end base;
41    struct draw_context *draw;
42
43    struct pt_emit *emit;
44    struct pt_so_emit *so_emit;
45    struct pt_fetch *fetch;
46    struct pt_post_vs *post_vs;
47
48    unsigned vertex_data_offset;
49    unsigned vertex_size;
50    unsigned input_prim;
51    unsigned opt;
52 };
53
54 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
55                                     unsigned prim,
56                                     unsigned opt,
57                                     unsigned *max_vertices )
58 {
59    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
60    struct draw_context *draw = fpme->draw;
61    struct draw_vertex_shader *vs = draw->vs.vertex_shader;
62    unsigned i;
63    unsigned instance_id_index = ~0;
64
65    unsigned gs_out_prim = (draw->gs.geometry_shader ? 
66                            draw->gs.geometry_shader->output_primitive :
67                            prim);
68
69    /* Add one to num_outputs because the pipeline occasionally tags on
70     * an additional texcoord, eg for AA lines.
71     */
72    unsigned nr = MAX2( vs->info.num_inputs,
73                        vs->info.num_outputs + 1 );
74
75    /* Scan for instanceID system value.
76     */
77    for (i = 0; i < vs->info.num_inputs; i++) {
78       if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
79          instance_id_index = i;
80          break;
81       }
82    }
83
84    fpme->input_prim = prim;
85    fpme->opt = opt;
86
87    /* Always leave room for the vertex header whether we need it or
88     * not.  It's hard to get rid of it in particular because of the
89     * viewport code in draw_pt_post_vs.c.  
90     */
91    fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
92
93    
94
95    draw_pt_fetch_prepare( fpme->fetch, 
96                           vs->info.num_inputs,
97                           fpme->vertex_size,
98                           instance_id_index );
99    /* XXX: it's not really gl rasterization rules we care about here,
100     * but gl vs dx9 clip spaces.
101     */
102    draw_pt_post_vs_prepare( fpme->post_vs,
103                             draw->clip_xy,
104                             draw->clip_z,
105                             draw->clip_user,
106                             draw->identity_viewport,
107                             (boolean)draw->rasterizer->gl_rasterization_rules,
108                             (draw->vs.edgeflag_output ? TRUE : FALSE) );
109
110    draw_pt_so_emit_prepare( fpme->so_emit );
111
112    if (!(opt & PT_PIPELINE)) {
113       draw_pt_emit_prepare( fpme->emit,
114                             gs_out_prim,
115                             max_vertices );
116
117       *max_vertices = MAX2( *max_vertices, 4096 );
118    }
119    else {
120       /* limit max fetches by limiting max_vertices */
121       *max_vertices = 4096;
122    }
123
124    /* No need to prepare the shader.
125     */
126    vs->prepare(vs, draw);
127 }
128
129
130 static void fetch( struct pt_fetch *fetch,
131                    const struct draw_fetch_info *fetch_info,
132                    char *output)
133 {
134    if (fetch_info->linear) {
135       draw_pt_fetch_run_linear( fetch,
136                                 fetch_info->start,
137                                 fetch_info->count,
138                                 output );
139    }
140    else {
141       draw_pt_fetch_run( fetch,
142                          fetch_info->elts,
143                          fetch_info->count,
144                          output );
145    }
146 }
147
148
149 static void pipeline(struct fetch_pipeline_middle_end *fpme,
150                      const struct draw_vertex_info *vert_info,
151                      const struct draw_prim_info *prim_info)
152 {
153    if (prim_info->linear)
154       draw_pipeline_run_linear( fpme->draw,
155                                 vert_info,
156                                 prim_info);
157    else
158       draw_pipeline_run( fpme->draw,
159                          vert_info,
160                          prim_info );
161 }
162
163 static void emit(struct pt_emit *emit,
164                  const struct draw_vertex_info *vert_info,
165                  const struct draw_prim_info *prim_info)
166 {
167    if (prim_info->linear) {
168       draw_pt_emit_linear(emit, vert_info, prim_info);
169    }
170    else {
171       draw_pt_emit(emit, vert_info, prim_info);
172    }
173 }
174
175
176 static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
177                                    const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 
178                                    unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
179                                    const struct draw_vertex_info *input_verts,
180                                    struct draw_vertex_info *output_verts )
181 {
182    output_verts->vertex_size = input_verts->vertex_size;
183    output_verts->stride = input_verts->vertex_size;
184    output_verts->count = input_verts->count;
185    output_verts->verts =
186       (struct vertex_header *)MALLOC(output_verts->vertex_size *
187                                      align(output_verts->count, 4));
188
189    vshader->run_linear(vshader,
190                        (const float (*)[4])input_verts->verts->data,
191                        (      float (*)[4])output_verts->verts->data,
192                        constants,
193                        const_size,
194                        input_verts->count,
195                        input_verts->vertex_size,
196                        input_verts->vertex_size);
197 }
198
199 static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
200                                     const struct draw_fetch_info *fetch_info,
201                                     const struct draw_prim_info *prim_info )
202 {
203    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
204    struct draw_context *draw = fpme->draw;
205    struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
206    struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
207    struct draw_prim_info gs_prim_info;
208    struct draw_vertex_info fetched_vert_info;
209    struct draw_vertex_info vs_vert_info;
210    struct draw_vertex_info gs_vert_info;
211    struct draw_vertex_info *vert_info;
212    unsigned opt = fpme->opt;
213
214    fetched_vert_info.count = fetch_info->count;
215    fetched_vert_info.vertex_size = fpme->vertex_size;
216    fetched_vert_info.stride = fpme->vertex_size;
217    fetched_vert_info.verts =
218       (struct vertex_header *)MALLOC(fpme->vertex_size *
219                                      align(fetch_info->count,  4));
220    if (!fetched_vert_info.verts) {
221       assert(0);
222       return;
223    }
224
225    /* Fetch into our vertex buffer.
226     */
227    fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );
228
229    /* Finished with fetch:
230     */
231    fetch_info = NULL;
232    vert_info = &fetched_vert_info;
233
234    /* Run the shader, note that this overwrites the data[] parts of
235     * the pipeline verts.
236     */
237    if (fpme->opt & PT_SHADE) {
238       draw_vertex_shader_run(vshader,
239                              draw->pt.user.vs_constants,
240                              draw->pt.user.vs_constants_size,
241                              vert_info,
242                              &vs_vert_info);
243
244       FREE(vert_info->verts);
245       vert_info = &vs_vert_info;
246    }
247
248    if ((fpme->opt & PT_SHADE) && gshader) {
249       draw_geometry_shader_run(gshader,
250                                draw->pt.user.gs_constants,
251                                draw->pt.user.gs_constants_size,
252                                vert_info,
253                                prim_info,
254                                &gs_vert_info,
255                                &gs_prim_info);
256
257       FREE(vert_info->verts);
258       vert_info = &gs_vert_info;
259       prim_info = &gs_prim_info;
260    }
261
262
263    /* Stream output needs to be done before clipping.
264     *
265     * XXX: Stream output surely needs to respect the prim_info->elt
266     *      lists.
267     */
268    draw_pt_so_emit( fpme->so_emit,
269                     vert_info,
270                     prim_info );
271
272    if (draw_pt_post_vs_run( fpme->post_vs,
273                             vert_info ))
274    {
275       opt |= PT_PIPELINE;
276    }
277
278    /* Do we need to run the pipeline?
279     */
280    if (opt & PT_PIPELINE) {
281       pipeline( fpme,
282                 vert_info,
283                 prim_info );
284    }
285    else {
286       emit( fpme->emit,
287             vert_info,
288             prim_info );
289    }
290    FREE(vert_info->verts);
291 }
292
293 static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
294                                 const unsigned *fetch_elts,
295                                 unsigned fetch_count,
296                                 const ushort *draw_elts,
297                                 unsigned draw_count,
298                                 unsigned prim_flags )
299 {
300    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
301    struct draw_fetch_info fetch_info;
302    struct draw_prim_info prim_info;
303
304    fetch_info.linear = FALSE;
305    fetch_info.start = 0;
306    fetch_info.elts = fetch_elts;
307    fetch_info.count = fetch_count;
308
309    prim_info.linear = FALSE;
310    prim_info.start = 0;
311    prim_info.count = draw_count;
312    prim_info.elts = draw_elts;
313    prim_info.prim = fpme->input_prim;
314    prim_info.flags = prim_flags;
315    prim_info.primitive_count = 1;
316    prim_info.primitive_lengths = &draw_count;
317
318    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
319 }
320
321
322 static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
323                                        unsigned start,
324                                        unsigned count,
325                                        unsigned prim_flags)
326 {
327    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
328    struct draw_fetch_info fetch_info;
329    struct draw_prim_info prim_info;
330
331    fetch_info.linear = TRUE;
332    fetch_info.start = start;
333    fetch_info.count = count;
334    fetch_info.elts = NULL;
335
336    prim_info.linear = TRUE;
337    prim_info.start = 0;
338    prim_info.count = count;
339    prim_info.elts = NULL;
340    prim_info.prim = fpme->input_prim;
341    prim_info.flags = prim_flags;
342    prim_info.primitive_count = 1;
343    prim_info.primitive_lengths = &count;
344
345    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
346 }
347
348
349
350 static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
351                                                unsigned start,
352                                                unsigned count,
353                                                const ushort *draw_elts,
354                                                unsigned draw_count,
355                                                unsigned prim_flags )
356 {
357    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
358    struct draw_fetch_info fetch_info;
359    struct draw_prim_info prim_info;
360
361    fetch_info.linear = TRUE;
362    fetch_info.start = start;
363    fetch_info.count = count;
364    fetch_info.elts = NULL;
365
366    prim_info.linear = FALSE;
367    prim_info.start = 0;
368    prim_info.count = draw_count;
369    prim_info.elts = draw_elts;
370    prim_info.prim = fpme->input_prim;
371    prim_info.flags = prim_flags;
372    prim_info.primitive_count = 1;
373    prim_info.primitive_lengths = &draw_count;
374
375    fetch_pipeline_generic( middle, &fetch_info, &prim_info );
376
377    return TRUE;
378 }
379
380
381
382 static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
383 {
384    /* nothing to do */
385 }
386
387 static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
388 {
389    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
390
391    if (fpme->fetch)
392       draw_pt_fetch_destroy( fpme->fetch );
393
394    if (fpme->emit)
395       draw_pt_emit_destroy( fpme->emit );
396
397    if (fpme->so_emit)
398       draw_pt_so_emit_destroy( fpme->so_emit );
399
400    if (fpme->post_vs)
401       draw_pt_post_vs_destroy( fpme->post_vs );
402
403    FREE(middle);
404 }
405
406
407 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
408 {
409    struct fetch_pipeline_middle_end *fpme = CALLOC_STRUCT( fetch_pipeline_middle_end );
410    if (!fpme)
411       goto fail;
412
413    fpme->base.prepare        = fetch_pipeline_prepare;
414    fpme->base.run            = fetch_pipeline_run;
415    fpme->base.run_linear     = fetch_pipeline_linear_run;
416    fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
417    fpme->base.finish         = fetch_pipeline_finish;
418    fpme->base.destroy        = fetch_pipeline_destroy;
419
420    fpme->draw = draw;
421
422    fpme->fetch = draw_pt_fetch_create( draw );
423    if (!fpme->fetch)
424       goto fail;
425
426    fpme->post_vs = draw_pt_post_vs_create( draw );
427    if (!fpme->post_vs)
428       goto fail;
429
430    fpme->emit = draw_pt_emit_create( draw );
431    if (!fpme->emit)
432       goto fail;
433
434    fpme->so_emit = draw_pt_so_emit_create( draw );
435    if (!fpme->so_emit)
436       goto fail;
437
438    return &fpme->base;
439
440  fail:
441    if (fpme)
442       fetch_pipeline_destroy( &fpme->base );
443
444    return NULL;
445 }