Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2010 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. #include "draw/draw_private.h"
  29. #include "draw/draw_vs.h"
  30. #include "draw/draw_gs.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.  
  36. #include "pipe/p_state.h"
  37.  
  38. #include "util/u_math.h"
  39. #include "util/u_memory.h"
  40.  
  41. struct pt_so_emit {
  42.    struct draw_context *draw;
  43.  
  44.    unsigned input_vertex_stride;
  45.    const float (*inputs)[4];
  46.    const float *pre_clip_pos;
  47.    boolean has_so;
  48.    boolean use_pre_clip_pos;
  49.    int pos_idx;
  50.    unsigned emitted_primitives;
  51.    unsigned generated_primitives;
  52. };
  53.  
  54. static const struct pipe_stream_output_info *
  55. draw_so_info(const struct draw_context *draw)
  56. {
  57.    const struct pipe_stream_output_info *state = NULL;
  58.  
  59.    if (draw->gs.geometry_shader) {
  60.       state = &draw->gs.geometry_shader->state.stream_output;
  61.    } else {
  62.       state = &draw->vs.vertex_shader->state.stream_output;
  63.    }
  64.  
  65.    return state;
  66. }
  67.  
  68. static INLINE boolean
  69. draw_has_so(const struct draw_context *draw)
  70. {
  71.    const struct pipe_stream_output_info *state = draw_so_info(draw);
  72.  
  73.    if (state && state->num_outputs > 0)
  74.       return TRUE;
  75.  
  76.    return FALSE;
  77. }
  78.  
  79. void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos)
  80. {
  81.    struct draw_context *draw = emit->draw;
  82.  
  83.    emit->use_pre_clip_pos = use_pre_clip_pos;
  84.    emit->has_so = draw_has_so(draw);
  85.    if (use_pre_clip_pos)
  86.       emit->pos_idx = draw_current_shader_position_output(draw);
  87.  
  88.    /* if we have a state with outputs make sure we have
  89.     * buffers to output to */
  90.    if (emit->has_so) {
  91.       boolean has_valid_buffer = FALSE;
  92.       unsigned i;
  93.       for (i = 0; i < draw->so.num_targets; ++i) {
  94.          if (draw->so.targets[i]) {
  95.             has_valid_buffer = TRUE;
  96.             break;
  97.          }
  98.       }
  99.       emit->has_so = has_valid_buffer;
  100.    }
  101.  
  102.    if (!emit->has_so)
  103.       return;
  104.  
  105.    /* XXX: need to flush to get prim_vbuf.c to release its allocation??
  106.     */
  107.    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
  108. }
  109.  
  110. static void so_emit_prim(struct pt_so_emit *so,
  111.                          unsigned *indices,
  112.                          unsigned num_vertices)
  113. {
  114.    unsigned slot, i;
  115.    unsigned input_vertex_stride = so->input_vertex_stride;
  116.    struct draw_context *draw = so->draw;
  117.    const float (*input_ptr)[4];
  118.    const float *pcp_ptr = NULL;
  119.    const struct pipe_stream_output_info *state = draw_so_info(draw);
  120.    float *buffer;
  121.    int buffer_total_bytes[PIPE_MAX_SO_BUFFERS];
  122.    boolean buffer_written[PIPE_MAX_SO_BUFFERS] = {0};
  123.  
  124.    input_ptr = so->inputs;
  125.    if (so->use_pre_clip_pos)
  126.       pcp_ptr = so->pre_clip_pos;
  127.  
  128.    ++so->generated_primitives;
  129.  
  130.    for (i = 0; i < draw->so.num_targets; i++) {
  131.       struct draw_so_target *target = draw->so.targets[i];
  132.       if (target) {
  133.          buffer_total_bytes[i] = target->internal_offset;
  134.       } else {
  135.          buffer_total_bytes[i] = 0;
  136.       }
  137.    }
  138.  
  139.    /* check have we space to emit prim first - if not don't do anything */
  140.    for (i = 0; i < num_vertices; ++i) {
  141.       unsigned ob;
  142.       for (slot = 0; slot < state->num_outputs; ++slot) {
  143.          unsigned num_comps = state->output[slot].num_components;
  144.          int ob = state->output[slot].output_buffer;
  145.          unsigned dst_offset = state->output[slot].dst_offset * sizeof(float);
  146.          unsigned write_size = num_comps * sizeof(float);
  147.          /* If a buffer is missing then that's equivalent to
  148.           * an overflow */
  149.          if (!draw->so.targets[ob]) {
  150.             return;
  151.          }
  152.          if ((buffer_total_bytes[ob] + write_size + dst_offset) >
  153.              draw->so.targets[ob]->target.buffer_size) {
  154.             return;
  155.          }
  156.       }
  157.       for (ob = 0; ob < draw->so.num_targets; ++ob) {
  158.          buffer_total_bytes[ob] += state->stride[ob] * sizeof(float);
  159.       }
  160.    }
  161.  
  162.    for (i = 0; i < num_vertices; ++i) {
  163.       const float (*input)[4];
  164.       const float *pre_clip_pos = NULL;
  165.       unsigned  ob;
  166.  
  167.       input = (const float (*)[4])(
  168.          (const char *)input_ptr + (indices[i] * input_vertex_stride));
  169.  
  170.       if (pcp_ptr)
  171.          pre_clip_pos = (const float *)(
  172.          (const char *)pcp_ptr + (indices[i] * input_vertex_stride));
  173.  
  174.       for (slot = 0; slot < state->num_outputs; ++slot) {
  175.          unsigned idx = state->output[slot].register_index;
  176.          unsigned start_comp = state->output[slot].start_component;
  177.          unsigned num_comps = state->output[slot].num_components;
  178.  
  179.          ob = state->output[slot].output_buffer;
  180.          buffer_written[ob] = TRUE;
  181.  
  182.          buffer = (float *)((char *)draw->so.targets[ob]->mapping +
  183.                             draw->so.targets[ob]->target.buffer_offset +
  184.                             draw->so.targets[ob]->internal_offset) +
  185.             state->output[slot].dst_offset;
  186.          
  187.          if (idx == so->pos_idx && pcp_ptr)
  188.             memcpy(buffer, &pre_clip_pos[start_comp],
  189.                    num_comps * sizeof(float));
  190.          else
  191.             memcpy(buffer, &input[idx][start_comp],
  192.                    num_comps * sizeof(float));
  193. #if 0
  194.          {
  195.             int j;
  196.             debug_printf("VERT[%d], offset = %d, slot[%d] sc = %d, num_c = %d, idx = %d = [",
  197.                          i,
  198.                          draw->so.targets[ob]->internal_offset,
  199.                          slot, start_comp, num_comps, idx);
  200.             for (j = 0; j < num_comps; ++j) {
  201.                unsigned *ubuffer = (unsigned*)buffer;
  202.                debug_printf("%d (0x%x), ", ubuffer[j], ubuffer[j]);
  203.             }
  204.             debug_printf("]\n");
  205.          }
  206. #endif
  207.       }
  208.       for (ob = 0; ob < draw->so.num_targets; ++ob) {
  209.          struct draw_so_target *target = draw->so.targets[ob];
  210.          if (target && buffer_written[ob]) {
  211.             target->internal_offset += state->stride[ob] * sizeof(float);
  212.          }
  213.       }
  214.    }
  215.    ++so->emitted_primitives;
  216. }
  217.  
  218. static void so_point(struct pt_so_emit *so, int idx)
  219. {
  220.    unsigned indices[1];
  221.  
  222.    indices[0] = idx;
  223.  
  224.    so_emit_prim(so, indices, 1);
  225. }
  226.  
  227. static void so_line(struct pt_so_emit *so, int i0, int i1)
  228. {
  229.    unsigned indices[2];
  230.  
  231.    indices[0] = i0;
  232.    indices[1] = i1;
  233.  
  234.    so_emit_prim(so, indices, 2);
  235. }
  236.  
  237. static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2)
  238. {
  239.    unsigned indices[3];
  240.  
  241.    indices[0] = i0;
  242.    indices[1] = i1;
  243.    indices[2] = i2;
  244.  
  245.    so_emit_prim(so, indices, 3);
  246. }
  247.  
  248.  
  249. #define FUNC         so_run_linear
  250. #define GET_ELT(idx) (start + (idx))
  251. #include "draw_so_emit_tmp.h"
  252.  
  253.  
  254. #define FUNC         so_run_elts
  255. #define LOCAL_VARS   const ushort *elts = input_prims->elts;
  256. #define GET_ELT(idx) (elts[start + (idx)])
  257. #include "draw_so_emit_tmp.h"
  258.  
  259.  
  260. void draw_pt_so_emit( struct pt_so_emit *emit,
  261.                       const struct draw_vertex_info *input_verts,
  262.                       const struct draw_prim_info *input_prims )
  263. {
  264.    struct draw_context *draw = emit->draw;
  265.    struct vbuf_render *render = draw->render;
  266.    unsigned start, i;
  267.  
  268.    if (!emit->has_so)
  269.       return;
  270.  
  271.    if (!draw->so.num_targets)
  272.       return;
  273.  
  274.    emit->emitted_primitives = 0;
  275.    emit->generated_primitives = 0;
  276.    emit->input_vertex_stride = input_verts->stride;
  277.    if (emit->use_pre_clip_pos)
  278.       emit->pre_clip_pos = input_verts->verts->pre_clip_pos;
  279.  
  280.    emit->inputs = (const float (*)[4])input_verts->verts->data;
  281.  
  282.    /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/
  283.    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
  284.  
  285.    for (start = i = 0; i < input_prims->primitive_count;
  286.         start += input_prims->primitive_lengths[i], i++)
  287.    {
  288.       unsigned count = input_prims->primitive_lengths[i];
  289.  
  290.       if (input_prims->linear) {
  291.          so_run_linear(emit, input_prims, input_verts,
  292.                        start, count);
  293.       } else {
  294.          so_run_elts(emit, input_prims, input_verts,
  295.                      start, count);
  296.       }
  297.    }
  298.  
  299.    render->set_stream_output_info(render,
  300.                                   emit->emitted_primitives,
  301.                                   emit->generated_primitives);
  302. }
  303.  
  304.  
  305. struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw )
  306. {
  307.    struct pt_so_emit *emit = CALLOC_STRUCT(pt_so_emit);
  308.    if (!emit)
  309.       return NULL;
  310.  
  311.    emit->draw = draw;
  312.  
  313.    return emit;
  314. }
  315.  
  316. void draw_pt_so_emit_destroy( struct pt_so_emit *emit )
  317. {
  318.    FREE(emit);
  319. }
  320.