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