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. /**
  29.  * Interface between 'draw' module's output and the softpipe rasterizer/setup
  30.  * code.  When the 'draw' module has finished filling a vertex buffer, the
  31.  * draw_arrays() functions below will be called.  Loop over the vertices and
  32.  * call the point/line/tri setup functions.
  33.  *
  34.  * Authors
  35.  *  Brian Paul
  36.  */
  37.  
  38.  
  39. #include "sp_context.h"
  40. #include "sp_setup.h"
  41. #include "sp_state.h"
  42. #include "sp_prim_vbuf.h"
  43. #include "draw/draw_context.h"
  44. #include "draw/draw_vbuf.h"
  45. #include "util/u_memory.h"
  46. #include "util/u_prim.h"
  47.  
  48.  
  49. #define SP_MAX_VBUF_INDEXES 1024
  50. #define SP_MAX_VBUF_SIZE    4096
  51.  
  52. typedef const float (*cptrf4)[4];
  53.  
  54. /**
  55.  * Subclass of vbuf_render.
  56.  */
  57. struct softpipe_vbuf_render
  58. {
  59.    struct vbuf_render base;
  60.    struct softpipe_context *softpipe;
  61.    struct setup_context *setup;
  62.  
  63.    uint prim;
  64.    uint vertex_size;
  65.    uint nr_vertices;
  66.    uint vertex_buffer_size;
  67.    void *vertex_buffer;
  68. };
  69.  
  70.  
  71. /** cast wrapper */
  72. static struct softpipe_vbuf_render *
  73. softpipe_vbuf_render(struct vbuf_render *vbr)
  74. {
  75.    return (struct softpipe_vbuf_render *) vbr;
  76. }
  77.  
  78.  
  79. /** This tells the draw module about our desired vertex layout */
  80. static const struct vertex_info *
  81. sp_vbuf_get_vertex_info(struct vbuf_render *vbr)
  82. {
  83.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  84.    return softpipe_get_vbuf_vertex_info(cvbr->softpipe);
  85. }
  86.  
  87.  
  88. static boolean
  89. sp_vbuf_allocate_vertices(struct vbuf_render *vbr,
  90.                           ushort vertex_size, ushort nr_vertices)
  91. {
  92.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  93.    unsigned size = vertex_size * nr_vertices;
  94.  
  95.    if (cvbr->vertex_buffer_size < size) {
  96.       align_free(cvbr->vertex_buffer);
  97.       cvbr->vertex_buffer = align_malloc(size, 16);
  98.       cvbr->vertex_buffer_size = size;
  99.    }
  100.  
  101.    cvbr->vertex_size = vertex_size;
  102.    cvbr->nr_vertices = nr_vertices;
  103.    
  104.    return cvbr->vertex_buffer != NULL;
  105. }
  106.  
  107.  
  108. static void
  109. sp_vbuf_release_vertices(struct vbuf_render *vbr)
  110. {
  111.    /* keep the old allocation for next time */
  112. }
  113.  
  114.  
  115. static void *
  116. sp_vbuf_map_vertices(struct vbuf_render *vbr)
  117. {
  118.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  119.    return cvbr->vertex_buffer;
  120. }
  121.  
  122.  
  123. static void
  124. sp_vbuf_unmap_vertices(struct vbuf_render *vbr,
  125.                        ushort min_index,
  126.                        ushort max_index )
  127. {
  128.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  129.    assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
  130.    (void) cvbr;
  131.    /* do nothing */
  132. }
  133.  
  134.  
  135. static void
  136. sp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
  137. {
  138.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  139.    struct setup_context *setup_ctx = cvbr->setup;
  140.    
  141.    sp_setup_prepare( setup_ctx );
  142.  
  143.    cvbr->softpipe->reduced_prim = u_reduced_prim(prim);
  144.    cvbr->prim = prim;
  145. }
  146.  
  147.  
  148. static INLINE cptrf4 get_vert( const void *vertex_buffer,
  149.                                int index,
  150.                                int stride )
  151. {
  152.    return (cptrf4)((char *)vertex_buffer + index * stride);
  153. }
  154.  
  155.  
  156. /**
  157.  * draw elements / indexed primitives
  158.  */
  159. static void
  160. sp_vbuf_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr)
  161. {
  162.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  163.    struct softpipe_context *softpipe = cvbr->softpipe;
  164.    const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
  165.    const void *vertex_buffer = cvbr->vertex_buffer;
  166.    struct setup_context *setup = cvbr->setup;
  167.    const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
  168.    unsigned i;
  169.  
  170.    switch (cvbr->prim) {
  171.    case PIPE_PRIM_POINTS:
  172.       for (i = 0; i < nr; i++) {
  173.          sp_setup_point( setup,
  174.                          get_vert(vertex_buffer, indices[i-0], stride) );
  175.       }
  176.       break;
  177.  
  178.    case PIPE_PRIM_LINES:
  179.       for (i = 1; i < nr; i += 2) {
  180.          sp_setup_line( setup,
  181.                         get_vert(vertex_buffer, indices[i-1], stride),
  182.                         get_vert(vertex_buffer, indices[i-0], stride) );
  183.       }
  184.       break;
  185.  
  186.    case PIPE_PRIM_LINE_STRIP:
  187.       for (i = 1; i < nr; i ++) {
  188.          sp_setup_line( setup,
  189.                         get_vert(vertex_buffer, indices[i-1], stride),
  190.                         get_vert(vertex_buffer, indices[i-0], stride) );
  191.       }
  192.       break;
  193.  
  194.    case PIPE_PRIM_LINE_LOOP:
  195.       for (i = 1; i < nr; i ++) {
  196.          sp_setup_line( setup,
  197.                         get_vert(vertex_buffer, indices[i-1], stride),
  198.                         get_vert(vertex_buffer, indices[i-0], stride) );
  199.       }
  200.       if (nr) {
  201.          sp_setup_line( setup,
  202.                         get_vert(vertex_buffer, indices[nr-1], stride),
  203.                         get_vert(vertex_buffer, indices[0], stride) );
  204.       }
  205.       break;
  206.  
  207.    case PIPE_PRIM_TRIANGLES:
  208.       for (i = 2; i < nr; i += 3) {
  209.          sp_setup_tri( setup,
  210.                        get_vert(vertex_buffer, indices[i-2], stride),
  211.                        get_vert(vertex_buffer, indices[i-1], stride),
  212.                        get_vert(vertex_buffer, indices[i-0], stride) );
  213.       }
  214.       break;
  215.  
  216.    case PIPE_PRIM_TRIANGLE_STRIP:
  217.       if (flatshade_first) {
  218.          for (i = 2; i < nr; i += 1) {
  219.             /* emit first triangle vertex as first triangle vertex */
  220.             sp_setup_tri( setup,
  221.                           get_vert(vertex_buffer, indices[i-2], stride),
  222.                           get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
  223.                           get_vert(vertex_buffer, indices[i-(i&1)], stride) );
  224.  
  225.          }
  226.       }
  227.       else {
  228.          for (i = 2; i < nr; i += 1) {
  229.             /* emit last triangle vertex as last triangle vertex */
  230.             sp_setup_tri( setup,
  231.                           get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
  232.                           get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
  233.                           get_vert(vertex_buffer, indices[i-0], stride) );
  234.          }
  235.       }
  236.       break;
  237.  
  238.    case PIPE_PRIM_TRIANGLE_FAN:
  239.       if (flatshade_first) {
  240.          for (i = 2; i < nr; i += 1) {
  241.             /* emit first non-spoke vertex as first vertex */
  242.             sp_setup_tri( setup,
  243.                           get_vert(vertex_buffer, indices[i-1], stride),
  244.                           get_vert(vertex_buffer, indices[i-0], stride),
  245.                           get_vert(vertex_buffer, indices[0], stride) );
  246.          }
  247.       }
  248.       else {
  249.          for (i = 2; i < nr; i += 1) {
  250.             /* emit last non-spoke vertex as last vertex */
  251.             sp_setup_tri( setup,
  252.                           get_vert(vertex_buffer, indices[0], stride),
  253.                           get_vert(vertex_buffer, indices[i-1], stride),
  254.                           get_vert(vertex_buffer, indices[i-0], stride) );
  255.          }
  256.       }
  257.       break;
  258.  
  259.    case PIPE_PRIM_QUADS:
  260.       /* GL quads don't follow provoking vertex convention */
  261.       if (flatshade_first) {
  262.          /* emit last quad vertex as first triangle vertex */
  263.          for (i = 3; i < nr; i += 4) {
  264.             sp_setup_tri( setup,
  265.                           get_vert(vertex_buffer, indices[i-0], stride),
  266.                           get_vert(vertex_buffer, indices[i-3], stride),
  267.                           get_vert(vertex_buffer, indices[i-2], stride) );
  268.  
  269.             sp_setup_tri( setup,
  270.                           get_vert(vertex_buffer, indices[i-0], stride),
  271.                           get_vert(vertex_buffer, indices[i-2], stride),
  272.                           get_vert(vertex_buffer, indices[i-1], stride) );
  273.          }
  274.       }
  275.       else {
  276.          /* emit last quad vertex as last triangle vertex */
  277.          for (i = 3; i < nr; i += 4) {
  278.             sp_setup_tri( setup,
  279.                           get_vert(vertex_buffer, indices[i-3], stride),
  280.                           get_vert(vertex_buffer, indices[i-2], stride),
  281.                           get_vert(vertex_buffer, indices[i-0], stride) );
  282.  
  283.             sp_setup_tri( setup,
  284.                           get_vert(vertex_buffer, indices[i-2], stride),
  285.                           get_vert(vertex_buffer, indices[i-1], stride),
  286.                           get_vert(vertex_buffer, indices[i-0], stride) );
  287.          }
  288.       }
  289.       break;
  290.  
  291.    case PIPE_PRIM_QUAD_STRIP:
  292.       /* GL quad strips don't follow provoking vertex convention */
  293.       if (flatshade_first) {
  294.          /* emit last quad vertex as first triangle vertex */
  295.          for (i = 3; i < nr; i += 2) {
  296.             sp_setup_tri( setup,
  297.                           get_vert(vertex_buffer, indices[i-0], stride),
  298.                           get_vert(vertex_buffer, indices[i-3], stride),
  299.                           get_vert(vertex_buffer, indices[i-2], stride) );
  300.             sp_setup_tri( setup,
  301.                           get_vert(vertex_buffer, indices[i-0], stride),
  302.                           get_vert(vertex_buffer, indices[i-1], stride),
  303.                           get_vert(vertex_buffer, indices[i-3], stride) );
  304.          }
  305.       }
  306.       else {
  307.          /* emit last quad vertex as last triangle vertex */
  308.          for (i = 3; i < nr; i += 2) {
  309.             sp_setup_tri( setup,
  310.                           get_vert(vertex_buffer, indices[i-3], stride),
  311.                           get_vert(vertex_buffer, indices[i-2], stride),
  312.                           get_vert(vertex_buffer, indices[i-0], stride) );
  313.             sp_setup_tri( setup,
  314.                           get_vert(vertex_buffer, indices[i-1], stride),
  315.                           get_vert(vertex_buffer, indices[i-3], stride),
  316.                           get_vert(vertex_buffer, indices[i-0], stride) );
  317.          }
  318.       }
  319.       break;
  320.  
  321.    case PIPE_PRIM_POLYGON:
  322.       /* Almost same as tri fan but the _first_ vertex specifies the flat
  323.        * shading color.
  324.        */
  325.       if (flatshade_first) {
  326.          /* emit first polygon  vertex as first triangle vertex */
  327.          for (i = 2; i < nr; i += 1) {
  328.             sp_setup_tri( setup,
  329.                           get_vert(vertex_buffer, indices[0], stride),
  330.                           get_vert(vertex_buffer, indices[i-1], stride),
  331.                           get_vert(vertex_buffer, indices[i-0], stride) );
  332.          }
  333.       }
  334.       else {
  335.          /* emit first polygon  vertex as last triangle vertex */
  336.          for (i = 2; i < nr; i += 1) {
  337.             sp_setup_tri( setup,
  338.                           get_vert(vertex_buffer, indices[i-1], stride),
  339.                           get_vert(vertex_buffer, indices[i-0], stride),
  340.                           get_vert(vertex_buffer, indices[0], stride) );
  341.          }
  342.       }
  343.       break;
  344.  
  345.    default:
  346.       assert(0);
  347.    }
  348. }
  349.  
  350.  
  351. /**
  352.  * This function is hit when the draw module is working in pass-through mode.
  353.  * It's up to us to convert the vertex array into point/line/tri prims.
  354.  */
  355. static void
  356. sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
  357. {
  358.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  359.    struct softpipe_context *softpipe = cvbr->softpipe;
  360.    struct setup_context *setup = cvbr->setup;
  361.    const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
  362.    const void *vertex_buffer =
  363.       (void *) get_vert(cvbr->vertex_buffer, start, stride);
  364.    const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
  365.    unsigned i;
  366.  
  367.    switch (cvbr->prim) {
  368.    case PIPE_PRIM_POINTS:
  369.       for (i = 0; i < nr; i++) {
  370.          sp_setup_point( setup,
  371.                          get_vert(vertex_buffer, i-0, stride) );
  372.       }
  373.       break;
  374.  
  375.    case PIPE_PRIM_LINES:
  376.       for (i = 1; i < nr; i += 2) {
  377.          sp_setup_line( setup,
  378.                         get_vert(vertex_buffer, i-1, stride),
  379.                         get_vert(vertex_buffer, i-0, stride) );
  380.       }
  381.       break;
  382.  
  383.    case PIPE_PRIM_LINES_ADJACENCY:
  384.       for (i = 3; i < nr; i += 4) {
  385.          sp_setup_line( setup,
  386.                         get_vert(vertex_buffer, i-2, stride),
  387.                         get_vert(vertex_buffer, i-1, stride) );
  388.       }
  389.       break;
  390.  
  391.    case PIPE_PRIM_LINE_STRIP:
  392.       for (i = 1; i < nr; i ++) {
  393.          sp_setup_line( setup,
  394.                      get_vert(vertex_buffer, i-1, stride),
  395.                      get_vert(vertex_buffer, i-0, stride) );
  396.       }
  397.       break;
  398.  
  399.    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
  400.       for (i = 3; i < nr; i++) {
  401.          sp_setup_line( setup,
  402.                      get_vert(vertex_buffer, i-2, stride),
  403.                      get_vert(vertex_buffer, i-1, stride) );
  404.       }
  405.       break;
  406.  
  407.    case PIPE_PRIM_LINE_LOOP:
  408.       for (i = 1; i < nr; i ++) {
  409.          sp_setup_line( setup,
  410.                         get_vert(vertex_buffer, i-1, stride),
  411.                         get_vert(vertex_buffer, i-0, stride) );
  412.       }
  413.       if (nr) {
  414.          sp_setup_line( setup,
  415.                         get_vert(vertex_buffer, nr-1, stride),
  416.                         get_vert(vertex_buffer, 0, stride) );
  417.       }
  418.       break;
  419.  
  420.    case PIPE_PRIM_TRIANGLES:
  421.       for (i = 2; i < nr; i += 3) {
  422.          sp_setup_tri( setup,
  423.                        get_vert(vertex_buffer, i-2, stride),
  424.                        get_vert(vertex_buffer, i-1, stride),
  425.                        get_vert(vertex_buffer, i-0, stride) );
  426.       }
  427.       break;
  428.  
  429.    case PIPE_PRIM_TRIANGLES_ADJACENCY:
  430.       for (i = 5; i < nr; i += 6) {
  431.          sp_setup_tri( setup,
  432.                        get_vert(vertex_buffer, i-5, stride),
  433.                        get_vert(vertex_buffer, i-3, stride),
  434.                        get_vert(vertex_buffer, i-1, stride) );
  435.       }
  436.       break;
  437.  
  438.    case PIPE_PRIM_TRIANGLE_STRIP:
  439.       if (flatshade_first) {
  440.          for (i = 2; i < nr; i++) {
  441.             /* emit first triangle vertex as first triangle vertex */
  442.             sp_setup_tri( setup,
  443.                           get_vert(vertex_buffer, i-2, stride),
  444.                           get_vert(vertex_buffer, i+(i&1)-1, stride),
  445.                           get_vert(vertex_buffer, i-(i&1), stride) );
  446.          }
  447.       }
  448.       else {
  449.          for (i = 2; i < nr; i++) {
  450.             /* emit last triangle vertex as last triangle vertex */
  451.             sp_setup_tri( setup,
  452.                           get_vert(vertex_buffer, i+(i&1)-2, stride),
  453.                           get_vert(vertex_buffer, i-(i&1)-1, stride),
  454.                           get_vert(vertex_buffer, i-0, stride) );
  455.          }
  456.       }
  457.       break;
  458.  
  459.    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
  460.       if (flatshade_first) {
  461.          for (i = 5; i < nr; i += 2) {
  462.             /* emit first triangle vertex as first triangle vertex */
  463.             sp_setup_tri( setup,
  464.                           get_vert(vertex_buffer, i-5, stride),
  465.                           get_vert(vertex_buffer, i+(i&1)*2-3, stride),
  466.                           get_vert(vertex_buffer, i-(i&1)*2-1, stride) );
  467.          }
  468.       }
  469.       else {
  470.          for (i = 5; i < nr; i += 2) {
  471.             /* emit last triangle vertex as last triangle vertex */
  472.             sp_setup_tri( setup,
  473.                           get_vert(vertex_buffer, i+(i&1)*2-5, stride),
  474.                           get_vert(vertex_buffer, i-(i&1)*2-3, stride),
  475.                           get_vert(vertex_buffer, i-1, stride) );
  476.          }
  477.       }
  478.       break;
  479.  
  480.    case PIPE_PRIM_TRIANGLE_FAN:
  481.       if (flatshade_first) {
  482.          for (i = 2; i < nr; i += 1) {
  483.             /* emit first non-spoke vertex as first vertex */
  484.             sp_setup_tri( setup,
  485.                           get_vert(vertex_buffer, i-1, stride),
  486.                           get_vert(vertex_buffer, i-0, stride),
  487.                           get_vert(vertex_buffer, 0, stride)  );
  488.          }
  489.       }
  490.       else {
  491.          for (i = 2; i < nr; i += 1) {
  492.             /* emit last non-spoke vertex as last vertex */
  493.             sp_setup_tri( setup,
  494.                           get_vert(vertex_buffer, 0, stride),
  495.                           get_vert(vertex_buffer, i-1, stride),
  496.                           get_vert(vertex_buffer, i-0, stride) );
  497.          }
  498.       }
  499.       break;
  500.  
  501.    case PIPE_PRIM_QUADS:
  502.       /* GL quads don't follow provoking vertex convention */
  503.       if (flatshade_first) {
  504.          /* emit last quad vertex as first triangle vertex */
  505.          for (i = 3; i < nr; i += 4) {
  506.             sp_setup_tri( setup,
  507.                           get_vert(vertex_buffer, i-0, stride),
  508.                           get_vert(vertex_buffer, i-3, stride),
  509.                           get_vert(vertex_buffer, i-2, stride) );
  510.             sp_setup_tri( setup,
  511.                           get_vert(vertex_buffer, i-0, stride),
  512.                           get_vert(vertex_buffer, i-2, stride),
  513.                           get_vert(vertex_buffer, i-1, stride) );
  514.          }
  515.       }
  516.       else {
  517.          /* emit last quad vertex as last triangle vertex */
  518.          for (i = 3; i < nr; i += 4) {
  519.             sp_setup_tri( setup,
  520.                           get_vert(vertex_buffer, i-3, stride),
  521.                           get_vert(vertex_buffer, i-2, stride),
  522.                           get_vert(vertex_buffer, i-0, stride) );
  523.             sp_setup_tri( setup,
  524.                           get_vert(vertex_buffer, i-2, stride),
  525.                           get_vert(vertex_buffer, i-1, stride),
  526.                           get_vert(vertex_buffer, i-0, stride) );
  527.          }
  528.       }
  529.       break;
  530.  
  531.    case PIPE_PRIM_QUAD_STRIP:
  532.       /* GL quad strips don't follow provoking vertex convention */
  533.       if (flatshade_first) {
  534.          /* emit last quad vertex as first triangle vertex */
  535.          for (i = 3; i < nr; i += 2) {
  536.             sp_setup_tri( setup,
  537.                           get_vert(vertex_buffer, i-0, stride),
  538.                           get_vert(vertex_buffer, i-3, stride),
  539.                           get_vert(vertex_buffer, i-2, stride) );
  540.             sp_setup_tri( setup,
  541.                           get_vert(vertex_buffer, i-0, stride),
  542.                           get_vert(vertex_buffer, i-1, stride),
  543.                           get_vert(vertex_buffer, i-3, stride) );
  544.          }
  545.       }
  546.       else {
  547.          /* emit last quad vertex as last triangle vertex */
  548.          for (i = 3; i < nr; i += 2) {
  549.             sp_setup_tri( setup,
  550.                           get_vert(vertex_buffer, i-3, stride),
  551.                           get_vert(vertex_buffer, i-2, stride),
  552.                           get_vert(vertex_buffer, i-0, stride) );
  553.             sp_setup_tri( setup,
  554.                           get_vert(vertex_buffer, i-1, stride),
  555.                           get_vert(vertex_buffer, i-3, stride),
  556.                           get_vert(vertex_buffer, i-0, stride) );
  557.          }
  558.       }
  559.       break;
  560.  
  561.    case PIPE_PRIM_POLYGON:
  562.       /* Almost same as tri fan but the _first_ vertex specifies the flat
  563.        * shading color.
  564.        */
  565.       if (flatshade_first) {
  566.          /* emit first polygon  vertex as first triangle vertex */
  567.          for (i = 2; i < nr; i += 1) {
  568.             sp_setup_tri( setup,
  569.                           get_vert(vertex_buffer, 0, stride),
  570.                           get_vert(vertex_buffer, i-1, stride),
  571.                           get_vert(vertex_buffer, i-0, stride) );
  572.          }
  573.       }
  574.       else {
  575.          /* emit first polygon  vertex as last triangle vertex */
  576.          for (i = 2; i < nr; i += 1) {
  577.             sp_setup_tri( setup,
  578.                           get_vert(vertex_buffer, i-1, stride),
  579.                           get_vert(vertex_buffer, i-0, stride),
  580.                           get_vert(vertex_buffer, 0, stride) );
  581.          }
  582.       }
  583.       break;
  584.  
  585.    default:
  586.       assert(0);
  587.    }
  588. }
  589.  
  590. static void
  591. sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices,
  592.                 uint prim_generated)
  593. {
  594.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  595.    struct softpipe_context *softpipe = cvbr->softpipe;
  596.  
  597.    softpipe->so_stats.num_primitives_written += primitives;
  598.    softpipe->so_stats.primitives_storage_needed =
  599.       vertices * 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/;
  600.    softpipe->num_primitives_generated += prim_generated;
  601. }
  602.  
  603. static void
  604. sp_vbuf_pipeline_statistics(
  605.    struct vbuf_render *vbr,
  606.    const struct pipe_query_data_pipeline_statistics *stats)
  607. {
  608.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  609.    struct softpipe_context *softpipe = cvbr->softpipe;
  610.  
  611.    softpipe->pipeline_statistics.ia_vertices +=
  612.       stats->ia_vertices;
  613.    softpipe->pipeline_statistics.ia_primitives +=
  614.       stats->ia_primitives;
  615.    softpipe->pipeline_statistics.vs_invocations +=
  616.       stats->vs_invocations;
  617.    softpipe->pipeline_statistics.gs_invocations +=
  618.       stats->gs_invocations;
  619.    softpipe->pipeline_statistics.gs_primitives +=
  620.       stats->gs_primitives;
  621.    softpipe->pipeline_statistics.c_invocations +=
  622.       stats->c_invocations;
  623. }
  624.  
  625.  
  626. static void
  627. sp_vbuf_destroy(struct vbuf_render *vbr)
  628. {
  629.    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
  630.    if (cvbr->vertex_buffer)
  631.       align_free(cvbr->vertex_buffer);
  632.    sp_setup_destroy_context(cvbr->setup);
  633.    FREE(cvbr);
  634. }
  635.  
  636.  
  637. /**
  638.  * Create the post-transform vertex handler for the given context.
  639.  */
  640. struct vbuf_render *
  641. sp_create_vbuf_backend(struct softpipe_context *sp)
  642. {
  643.    struct softpipe_vbuf_render *cvbr = CALLOC_STRUCT(softpipe_vbuf_render);
  644.  
  645.    assert(sp->draw);
  646.  
  647.    cvbr->base.max_indices = SP_MAX_VBUF_INDEXES;
  648.    cvbr->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE;
  649.  
  650.    cvbr->base.get_vertex_info = sp_vbuf_get_vertex_info;
  651.    cvbr->base.allocate_vertices = sp_vbuf_allocate_vertices;
  652.    cvbr->base.map_vertices = sp_vbuf_map_vertices;
  653.    cvbr->base.unmap_vertices = sp_vbuf_unmap_vertices;
  654.    cvbr->base.set_primitive = sp_vbuf_set_primitive;
  655.    cvbr->base.draw_elements = sp_vbuf_draw_elements;
  656.    cvbr->base.draw_arrays = sp_vbuf_draw_arrays;
  657.    cvbr->base.release_vertices = sp_vbuf_release_vertices;
  658.    cvbr->base.set_stream_output_info = sp_vbuf_so_info;
  659.    cvbr->base.pipeline_statistics = sp_vbuf_pipeline_statistics;
  660.    cvbr->base.destroy = sp_vbuf_destroy;
  661.  
  662.    cvbr->softpipe = sp;
  663.  
  664.    cvbr->setup = sp_setup_create_context(cvbr->softpipe);
  665.  
  666.    return &cvbr->base;
  667. }
  668.