Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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. /* Authors:  Keith Whitwell <keith@tungstengraphics.com>
  29.  */
  30.  
  31. #include "util/u_math.h"
  32. #include "util/u_memory.h"
  33. #include "pipe/p_defines.h"
  34. #include "pipe/p_shader_tokens.h"
  35. #include "draw_vs.h"
  36. #include "draw_pipe.h"
  37.  
  38. struct twoside_stage {
  39.    struct draw_stage stage;
  40.    float sign;         /**< +1 or -1 */
  41.    int attrib_front0, attrib_back0;
  42.    int attrib_front1, attrib_back1;
  43. };
  44.  
  45.  
  46. static INLINE struct twoside_stage *twoside_stage( struct draw_stage *stage )
  47. {
  48.    return (struct twoside_stage *)stage;
  49. }
  50.  
  51. /**
  52.  * Copy back color(s) to front color(s).
  53.  */
  54. static INLINE struct vertex_header *
  55. copy_bfc( struct twoside_stage *twoside,
  56.           const struct vertex_header *v,
  57.           unsigned idx )
  58. {  
  59.    struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx );
  60.  
  61.    if (twoside->attrib_back0 >= 0 && twoside->attrib_front0 >= 0) {
  62.       COPY_4FV(tmp->data[twoside->attrib_front0],
  63.                tmp->data[twoside->attrib_back0]);
  64.    }
  65.    if (twoside->attrib_back1 >= 0 && twoside->attrib_front1 >= 0) {
  66.       COPY_4FV(tmp->data[twoside->attrib_front1],
  67.                tmp->data[twoside->attrib_back1]);
  68.    }
  69.  
  70.    return tmp;
  71. }
  72.  
  73.  
  74. /* Twoside tri:
  75.  */
  76. static void twoside_tri( struct draw_stage *stage,
  77.                          struct prim_header *header )
  78. {
  79.    struct twoside_stage *twoside = twoside_stage(stage);
  80.  
  81.    if (header->det * twoside->sign < 0.0) {
  82.       /* this is a back-facing triangle */
  83.       struct prim_header tmp;
  84.  
  85.       tmp.det = header->det;
  86.       tmp.flags = header->flags;
  87.       tmp.pad = header->pad;
  88.       /* copy back attribs to front attribs */
  89.       tmp.v[0] = copy_bfc(twoside, header->v[0], 0);
  90.       tmp.v[1] = copy_bfc(twoside, header->v[1], 1);
  91.       tmp.v[2] = copy_bfc(twoside, header->v[2], 2);
  92.  
  93.       stage->next->tri( stage->next, &tmp );
  94.    }
  95.    else {
  96.       stage->next->tri( stage->next, header );
  97.    }
  98. }
  99.  
  100.  
  101.  
  102. static void twoside_first_tri( struct draw_stage *stage,
  103.                                struct prim_header *header )
  104. {
  105.    struct twoside_stage *twoside = twoside_stage(stage);
  106.    const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
  107.    uint i;
  108.  
  109.    twoside->attrib_front0 = -1;
  110.    twoside->attrib_front1 = -1;
  111.    twoside->attrib_back0 = -1;
  112.    twoside->attrib_back1 = -1;
  113.  
  114.    /* Find which vertex shader outputs are front/back colors */
  115.    for (i = 0; i < vs->info.num_outputs; i++) {
  116.       if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
  117.          if (vs->info.output_semantic_index[i] == 0)
  118.             twoside->attrib_front0 = i;
  119.          else
  120.             twoside->attrib_front1 = i;
  121.       }
  122.       if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
  123.          if (vs->info.output_semantic_index[i] == 0)
  124.             twoside->attrib_back0 = i;
  125.          else
  126.             twoside->attrib_back1 = i;
  127.       }
  128.    }
  129.  
  130.    /*
  131.     * We'll multiply the primitive's determinant by this sign to determine
  132.     * if the triangle is back-facing (negative).
  133.     * sign = -1 for CCW, +1 for CW
  134.     */
  135.    twoside->sign = stage->draw->rasterizer->front_ccw ? -1.0f : 1.0f;
  136.  
  137.    stage->tri = twoside_tri;
  138.    stage->tri( stage, header );
  139. }
  140.  
  141.  
  142. static void twoside_flush( struct draw_stage *stage, unsigned flags )
  143. {
  144.    stage->tri = twoside_first_tri;
  145.    stage->next->flush( stage->next, flags );
  146. }
  147.  
  148.  
  149. static void twoside_reset_stipple_counter( struct draw_stage *stage )
  150. {
  151.    stage->next->reset_stipple_counter( stage->next );
  152. }
  153.  
  154.  
  155. static void twoside_destroy( struct draw_stage *stage )
  156. {
  157.    draw_free_temp_verts( stage );
  158.    FREE( stage );
  159. }
  160.  
  161.  
  162. /**
  163.  * Create twoside pipeline stage.
  164.  */
  165. struct draw_stage *draw_twoside_stage( struct draw_context *draw )
  166. {
  167.    struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage);
  168.    if (twoside == NULL)
  169.       goto fail;
  170.  
  171.    twoside->stage.draw = draw;
  172.    twoside->stage.name = "twoside";
  173.    twoside->stage.next = NULL;
  174.    twoside->stage.point = draw_pipe_passthrough_point;
  175.    twoside->stage.line = draw_pipe_passthrough_line;
  176.    twoside->stage.tri = twoside_first_tri;
  177.    twoside->stage.flush = twoside_flush;
  178.    twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter;
  179.    twoside->stage.destroy = twoside_destroy;
  180.  
  181.    if (!draw_alloc_temp_verts( &twoside->stage, 3 ))
  182.       goto fail;
  183.  
  184.    return &twoside->stage;
  185.  
  186.  fail:
  187.    if (twoside)
  188.       twoside->stage.destroy( &twoside->stage );
  189.  
  190.    return NULL;
  191. }
  192.