Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 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. /* Authors:  Keith Whitwell <keithw@vmware.com>
  29.  */
  30.  
  31. #include "util/u_math.h"
  32. #include "util/u_memory.h"
  33.  
  34. #include "pipe/p_shader_tokens.h"
  35. #include "draw_vs.h"
  36. #include "draw_fs.h"
  37. #include "draw_pipe.h"
  38.  
  39.  
  40. /** subclass of draw_stage */
  41. struct flat_stage
  42. {
  43.    struct draw_stage stage;
  44.  
  45.    uint num_flat_attribs;
  46.    uint flat_attribs[PIPE_MAX_SHADER_OUTPUTS];  /* flatshaded attribs */
  47. };
  48.  
  49.  
  50. static INLINE struct flat_stage *
  51. flat_stage(struct draw_stage *stage)
  52. {
  53.    return (struct flat_stage *) stage;
  54. }
  55.  
  56.  
  57. /** Copy all the constant attributes from 'src' vertex to 'dst' vertex */
  58. static INLINE void copy_flats( struct draw_stage *stage,
  59.                                struct vertex_header *dst,
  60.                                const struct vertex_header *src )
  61. {
  62.    const struct flat_stage *flat = flat_stage(stage);
  63.    uint i;
  64.  
  65.    for (i = 0; i < flat->num_flat_attribs; i++) {
  66.       const uint attr = flat->flat_attribs[i];
  67.       COPY_4FV(dst->data[attr], src->data[attr]);
  68.    }
  69. }
  70.  
  71.  
  72. /** Copy all the color attributes from src vertex to dst0 & dst1 vertices */
  73. static INLINE void copy_flats2( struct draw_stage *stage,
  74.                                 struct vertex_header *dst0,
  75.                                 struct vertex_header *dst1,
  76.                                 const struct vertex_header *src )
  77. {
  78.    const struct flat_stage *flat = flat_stage(stage);
  79.    uint i;
  80.    for (i = 0; i < flat->num_flat_attribs; i++) {
  81.       const uint attr = flat->flat_attribs[i];
  82.       COPY_4FV(dst0->data[attr], src->data[attr]);
  83.       COPY_4FV(dst1->data[attr], src->data[attr]);
  84.    }
  85. }
  86.  
  87.  
  88. /**
  89.  * Flatshade tri. Not required for clipping which handles this on its own,
  90.  * but required for unfilled tris and other primitive-changing stages
  91.  * (like widelines). If no such stages are active, handled by hardware.
  92.  */
  93. static void flatshade_tri_0( struct draw_stage *stage,
  94.                              struct prim_header *header )
  95. {
  96.    struct prim_header tmp;
  97.  
  98.    tmp.det = header->det;
  99.    tmp.flags = header->flags;
  100.    tmp.pad = header->pad;
  101.    tmp.v[0] = header->v[0];
  102.    tmp.v[1] = dup_vert(stage, header->v[1], 0);
  103.    tmp.v[2] = dup_vert(stage, header->v[2], 1);
  104.  
  105.    copy_flats2(stage, tmp.v[1], tmp.v[2], tmp.v[0]);
  106.  
  107.    stage->next->tri( stage->next, &tmp );
  108. }
  109.  
  110.  
  111. static void flatshade_tri_2( struct draw_stage *stage,
  112.                              struct prim_header *header )
  113. {
  114.    struct prim_header tmp;
  115.  
  116.    tmp.det = header->det;
  117.    tmp.flags = header->flags;
  118.    tmp.pad = header->pad;
  119.    tmp.v[0] = dup_vert(stage, header->v[0], 0);
  120.    tmp.v[1] = dup_vert(stage, header->v[1], 1);
  121.    tmp.v[2] = header->v[2];
  122.  
  123.    copy_flats2(stage, tmp.v[0], tmp.v[1], tmp.v[2]);
  124.  
  125.    stage->next->tri( stage->next, &tmp );
  126. }
  127.  
  128.  
  129. /**
  130.  * Flatshade line.
  131.  */
  132. static void flatshade_line_0( struct draw_stage *stage,
  133.                               struct prim_header *header )
  134. {
  135.    struct prim_header tmp;
  136.  
  137.    tmp.det = header->det;
  138.    tmp.flags = header->flags;
  139.    tmp.pad = header->pad;
  140.    tmp.v[0] = header->v[0];
  141.    tmp.v[1] = dup_vert(stage, header->v[1], 0);
  142.  
  143.    copy_flats(stage, tmp.v[1], tmp.v[0]);
  144.  
  145.    stage->next->line( stage->next, &tmp );
  146. }
  147.  
  148.  
  149. static void flatshade_line_1( struct draw_stage *stage,
  150.                               struct prim_header *header )
  151. {
  152.    struct prim_header tmp;
  153.  
  154.    tmp.det = header->det;
  155.    tmp.flags = header->flags;
  156.    tmp.pad = header->pad;
  157.    tmp.v[0] = dup_vert(stage, header->v[0], 0);
  158.    tmp.v[1] = header->v[1];
  159.  
  160.    copy_flats(stage, tmp.v[0], tmp.v[1]);
  161.  
  162.    stage->next->line( stage->next, &tmp );
  163. }
  164.  
  165.  
  166. static int
  167. find_interp(const struct draw_fragment_shader *fs, int *indexed_interp,
  168.             uint semantic_name, uint semantic_index)
  169. {
  170.    int interp;
  171.    /* If it's gl_{Front,Back}{,Secondary}Color, pick up the mode
  172.     * from the array we've filled before. */
  173.    if (semantic_name == TGSI_SEMANTIC_COLOR ||
  174.        semantic_name == TGSI_SEMANTIC_BCOLOR) {
  175.       interp = indexed_interp[semantic_index];
  176.    } else {
  177.       /* Otherwise, search in the FS inputs, with a decent default
  178.        * if we don't find it.
  179.        */
  180.       uint j;
  181.       interp = TGSI_INTERPOLATE_PERSPECTIVE;
  182.       if (fs) {
  183.          for (j = 0; j < fs->info.num_inputs; j++) {
  184.             if (semantic_name == fs->info.input_semantic_name[j] &&
  185.                 semantic_index == fs->info.input_semantic_index[j]) {
  186.                interp = fs->info.input_interpolate[j];
  187.                break;
  188.             }
  189.          }
  190.       }
  191.    }
  192.    return interp;
  193. }
  194.  
  195.  
  196. static void flatshade_init_state( struct draw_stage *stage )
  197. {
  198.    struct flat_stage *flat = flat_stage(stage);
  199.    const struct draw_context *draw = stage->draw;
  200.    const struct draw_fragment_shader *fs = draw->fs.fragment_shader;
  201.    const struct tgsi_shader_info *info = draw_get_shader_info(draw);
  202.    uint i, j;
  203.  
  204.    /* Find which vertex shader outputs need constant interpolation, make a list */
  205.  
  206.    /* XXX: this code is a near exact copy of the one in clip_init_state.
  207.     * The latter also cares about perspective though.
  208.     */
  209.  
  210.    /* First pick up the interpolation mode for
  211.     * gl_Color/gl_SecondaryColor, with the correct default.
  212.     */
  213.    int indexed_interp[2];
  214.    indexed_interp[0] = indexed_interp[1] = draw->rasterizer->flatshade ?
  215.       TGSI_INTERPOLATE_CONSTANT : TGSI_INTERPOLATE_PERSPECTIVE;
  216.  
  217.    if (fs) {
  218.       for (i = 0; i < fs->info.num_inputs; i++) {
  219.          if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
  220.             if (fs->info.input_interpolate[i] != TGSI_INTERPOLATE_COLOR)
  221.                indexed_interp[fs->info.input_semantic_index[i]] = fs->info.input_interpolate[i];
  222.          }
  223.       }
  224.    }
  225.  
  226.    /* Then resolve the interpolation mode for every output attribute.
  227.     *
  228.     * Given how the rest of the code, the most efficient way is to
  229.     * have a vector of flat-mode attributes.
  230.     */
  231.    flat->num_flat_attribs = 0;
  232.    for (i = 0; i < info->num_outputs; i++) {
  233.       /* Find the interpolation mode for a specific attribute */
  234.       int interp = find_interp(fs, indexed_interp,
  235.                                info->output_semantic_name[i],
  236.                                info->output_semantic_index[i]);
  237.       /* If it's flat, add it to the flat vector. */
  238.  
  239.       if (interp == TGSI_INTERPOLATE_CONSTANT) {
  240.          flat->flat_attribs[flat->num_flat_attribs] = i;
  241.          flat->num_flat_attribs++;
  242.       }
  243.    }
  244.    /* Search the extra vertex attributes */
  245.    for (j = 0; j < draw->extra_shader_outputs.num; j++) {
  246.       /* Find the interpolation mode for a specific attribute */
  247.       int interp = find_interp(fs, indexed_interp,
  248.                                draw->extra_shader_outputs.semantic_name[j],
  249.                                draw->extra_shader_outputs.semantic_index[j]);
  250.       /* If it's flat, add it to the flat vector. */
  251.       if (interp == TGSI_INTERPOLATE_CONSTANT) {
  252.          flat->flat_attribs[flat->num_flat_attribs] = i + j;
  253.          flat->num_flat_attribs++;
  254.       }
  255.    }
  256.  
  257.    /* Choose flatshade routine according to provoking vertex:
  258.     */
  259.    if (draw->rasterizer->flatshade_first) {
  260.       stage->line = flatshade_line_0;
  261.       stage->tri = flatshade_tri_0;
  262.    }
  263.    else {
  264.       stage->line = flatshade_line_1;
  265.       stage->tri = flatshade_tri_2;
  266.    }
  267. }
  268.  
  269. static void flatshade_first_tri( struct draw_stage *stage,
  270.                                  struct prim_header *header )
  271. {
  272.    flatshade_init_state( stage );
  273.    stage->tri( stage, header );
  274. }
  275.  
  276. static void flatshade_first_line( struct draw_stage *stage,
  277.                                   struct prim_header *header )
  278. {
  279.    flatshade_init_state( stage );
  280.    stage->line( stage, header );
  281. }
  282.  
  283.  
  284. static void flatshade_flush( struct draw_stage *stage,
  285.                              unsigned flags )
  286. {
  287.    stage->tri = flatshade_first_tri;
  288.    stage->line = flatshade_first_line;
  289.    stage->next->flush( stage->next, flags );
  290. }
  291.  
  292.  
  293. static void flatshade_reset_stipple_counter( struct draw_stage *stage )
  294. {
  295.    stage->next->reset_stipple_counter( stage->next );
  296. }
  297.  
  298.  
  299. static void flatshade_destroy( struct draw_stage *stage )
  300. {
  301.    draw_free_temp_verts( stage );
  302.    FREE( stage );
  303. }
  304.  
  305.  
  306. /**
  307.  * Create flatshading drawing stage.
  308.  */
  309. struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
  310. {
  311.    struct flat_stage *flatshade = CALLOC_STRUCT(flat_stage);
  312.    if (flatshade == NULL)
  313.       goto fail;
  314.  
  315.    flatshade->stage.draw = draw;
  316.    flatshade->stage.name = "flatshade";
  317.    flatshade->stage.next = NULL;
  318.    flatshade->stage.point = draw_pipe_passthrough_point;
  319.    flatshade->stage.line = flatshade_first_line;
  320.    flatshade->stage.tri = flatshade_first_tri;
  321.    flatshade->stage.flush = flatshade_flush;
  322.    flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
  323.    flatshade->stage.destroy = flatshade_destroy;
  324.  
  325.    if (!draw_alloc_temp_verts( &flatshade->stage, 2 ))
  326.       goto fail;
  327.  
  328.    return &flatshade->stage;
  329.  
  330.  fail:
  331.    if (flatshade)
  332.       flatshade->stage.destroy( &flatshade->stage );
  333.  
  334.    return NULL;
  335. }
  336.  
  337.  
  338.