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.   * Authors:
  30.   *   Keith Whitwell <keith@tungstengraphics.com>
  31.   */
  32.  
  33. #include "util/u_memory.h"
  34. #include "util/u_math.h"
  35. #include "draw/draw_context.h"
  36. #include "draw/draw_private.h"
  37. #include "draw/draw_vbuf.h"
  38. #include "draw/draw_vertex.h"
  39. #include "draw/draw_vs.h"
  40. #include "translate/translate.h"
  41.  
  42. /* A first pass at incorporating vertex fetch/emit functionality into
  43.  */
  44. struct draw_vs_variant_generic {
  45.    struct draw_vs_variant base;
  46.  
  47.    struct draw_vertex_shader *shader;
  48.    struct draw_context *draw;
  49.    
  50.    /* Basic plan is to run these two translate functions before/after
  51.     * the vertex shader's existing run_linear() routine to simulate
  52.     * the inclusion of this functionality into the shader...  
  53.     *
  54.     * Next will look at actually including it.
  55.     */
  56.    struct translate *fetch;
  57.    struct translate *emit;
  58.  
  59.    unsigned temp_vertex_stride;
  60. };
  61.  
  62.  
  63.  
  64.  
  65.  
  66. static void vsvg_set_buffer( struct draw_vs_variant *variant,
  67.                              unsigned buffer,
  68.                              const void *ptr,
  69.                              unsigned stride,
  70.                              unsigned max_index )
  71. {
  72.    struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
  73.  
  74.    vsvg->fetch->set_buffer(vsvg->fetch,
  75.                            buffer,
  76.                            ptr,
  77.                            stride,
  78.                            max_index );
  79. }
  80.  
  81. static const struct pipe_viewport_state *
  82. find_viewport(struct draw_context *draw,
  83.               char *buffer,
  84.               unsigned vertex_idx,
  85.               unsigned stride)
  86. {
  87.    int viewport_index_output =
  88.       draw_current_shader_viewport_index_output(draw);
  89.    char *ptr = buffer + vertex_idx * stride;
  90.    unsigned *data = (unsigned *)ptr;
  91.    int viewport_index =
  92.       draw_current_shader_uses_viewport_index(draw) ?
  93.       data[viewport_index_output * 4] : 0;
  94.  
  95.    viewport_index = draw_clamp_viewport_idx(viewport_index);
  96.  
  97.    return &draw->viewports[viewport_index];
  98. }
  99.    
  100.  
  101. /* Mainly for debug at this stage:
  102.  */
  103. static void do_rhw_viewport( struct draw_vs_variant_generic *vsvg,
  104.                              unsigned count,
  105.                              void *output_buffer )
  106. {
  107.    char *ptr = (char *)output_buffer;
  108.    unsigned stride = vsvg->temp_vertex_stride;
  109.    unsigned j;
  110.  
  111.    ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
  112.  
  113.    for (j = 0; j < count; j++, ptr += stride) {
  114.       const struct pipe_viewport_state *viewport =
  115.          find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
  116.                        j, stride);
  117.       const float *scale = viewport->scale;
  118.       const float *trans = viewport->translate;
  119.       float *data = (float *)ptr;
  120.       float w = 1.0f / data[3];
  121.  
  122.       data[0] = data[0] * w * scale[0] + trans[0];
  123.       data[1] = data[1] * w * scale[1] + trans[1];
  124.       data[2] = data[2] * w * scale[2] + trans[2];
  125.       data[3] = w;
  126.    }
  127. }
  128.  
  129. static void do_viewport( struct draw_vs_variant_generic *vsvg,
  130.                          unsigned count,
  131.                          void *output_buffer )
  132. {
  133.    char *ptr = (char *)output_buffer;
  134.    unsigned stride = vsvg->temp_vertex_stride;
  135.    unsigned j;
  136.  
  137.    ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
  138.  
  139.    for (j = 0; j < count; j++, ptr += stride) {
  140.       const struct pipe_viewport_state *viewport =
  141.          find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
  142.                        j, stride);
  143.       const float *scale = viewport->scale;
  144.       const float *trans = viewport->translate;
  145.       float *data = (float *)ptr;
  146.  
  147.       data[0] = data[0] * scale[0] + trans[0];
  148.       data[1] = data[1] * scale[1] + trans[1];
  149.       data[2] = data[2] * scale[2] + trans[2];
  150.    }
  151. }
  152.                          
  153.  
  154. static void PIPE_CDECL vsvg_run_elts( struct draw_vs_variant *variant,
  155.                                       const unsigned *elts,
  156.                                       unsigned count,
  157.                                       void *output_buffer)
  158. {
  159.    struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
  160.    unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
  161.    void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
  162.    
  163.    if (0) debug_printf("%s %d \n", __FUNCTION__,  count);
  164.                        
  165.    /* Want to do this in small batches for cache locality?
  166.     */
  167.    
  168.    vsvg->fetch->run_elts( vsvg->fetch,
  169.                           elts,
  170.                           count,
  171.                           vsvg->draw->start_instance,
  172.                           vsvg->draw->instance_id,
  173.                           temp_buffer );
  174.  
  175.    vsvg->base.vs->run_linear( vsvg->base.vs,
  176.                               temp_buffer,
  177.                               temp_buffer,
  178.                               vsvg->base.vs->draw->pt.user.vs_constants,
  179.                               vsvg->base.vs->draw->pt.user.vs_constants_size,
  180.                               count,
  181.                               temp_vertex_stride,
  182.                               temp_vertex_stride);
  183.  
  184.    /* FIXME: geometry shading? */
  185.  
  186.    if (vsvg->base.key.clip) {
  187.       /* not really handling clipping, just do the rhw so we can
  188.        * see the results...
  189.        */
  190.       do_rhw_viewport( vsvg,
  191.                        count,
  192.                        temp_buffer );
  193.    }
  194.    else if (vsvg->base.key.viewport) {
  195.       do_viewport( vsvg,
  196.                    count,
  197.                    temp_buffer );
  198.    }
  199.  
  200.  
  201.    vsvg->emit->set_buffer( vsvg->emit,
  202.                            0,
  203.                            temp_buffer,
  204.                            temp_vertex_stride,
  205.                            ~0 );
  206.  
  207.    vsvg->emit->set_buffer( vsvg->emit,
  208.                            1,
  209.                            &vsvg->draw->rasterizer->point_size,
  210.                            0,
  211.                            ~0 );
  212.  
  213.    vsvg->emit->run( vsvg->emit,
  214.                     0, count,
  215.                     vsvg->draw->start_instance,
  216.                     vsvg->draw->instance_id,
  217.                     output_buffer );
  218.  
  219.    FREE(temp_buffer);
  220. }
  221.  
  222.  
  223. static void PIPE_CDECL vsvg_run_linear( struct draw_vs_variant *variant,
  224.                                         unsigned start,
  225.                                         unsigned count,
  226.                                         void *output_buffer )
  227. {
  228.    struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
  229.    unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
  230.    void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
  231.        
  232.    if (0) debug_printf("%s %d %d (sz %d, %d)\n", __FUNCTION__, start, count,
  233.                        vsvg->base.key.output_stride,
  234.                        temp_vertex_stride);
  235.  
  236.    vsvg->fetch->run( vsvg->fetch,
  237.                      start,
  238.                      count,
  239.                      vsvg->draw->start_instance,
  240.                      vsvg->draw->instance_id,
  241.                      temp_buffer );
  242.  
  243.    vsvg->base.vs->run_linear( vsvg->base.vs,
  244.                               temp_buffer,
  245.                               temp_buffer,
  246.                               vsvg->base.vs->draw->pt.user.vs_constants,
  247.                               vsvg->base.vs->draw->pt.user.vs_constants_size,
  248.                               count,
  249.                               temp_vertex_stride,
  250.                               temp_vertex_stride);
  251.  
  252.    if (vsvg->base.key.clip) {
  253.       /* not really handling clipping, just do the rhw so we can
  254.        * see the results...
  255.        */
  256.       do_rhw_viewport( vsvg,
  257.                        count,
  258.                        temp_buffer );
  259.    }
  260.    else if (vsvg->base.key.viewport) {
  261.       do_viewport( vsvg,
  262.                    count,
  263.                    temp_buffer );
  264.    }
  265.  
  266.    vsvg->emit->set_buffer( vsvg->emit,
  267.                            0,
  268.                            temp_buffer,
  269.                            temp_vertex_stride,
  270.                            ~0 );
  271.    
  272.    vsvg->emit->set_buffer( vsvg->emit,
  273.                            1,
  274.                            &vsvg->draw->rasterizer->point_size,
  275.                            0,
  276.                            ~0 );
  277.    
  278.    vsvg->emit->run( vsvg->emit,
  279.                     0, count,
  280.                     vsvg->draw->start_instance,
  281.                     vsvg->draw->instance_id,
  282.                     output_buffer );
  283.  
  284.    FREE(temp_buffer);
  285. }
  286.  
  287.  
  288.  
  289.  
  290.  
  291. static void vsvg_destroy( struct draw_vs_variant *variant )
  292. {
  293.    FREE(variant);
  294. }
  295.  
  296.  
  297. struct draw_vs_variant *
  298. draw_vs_create_variant_generic( struct draw_vertex_shader *vs,
  299.                                 const struct draw_vs_variant_key *key )
  300. {
  301.    unsigned i;
  302.    struct translate_key fetch, emit;
  303.  
  304.    struct draw_vs_variant_generic *vsvg = CALLOC_STRUCT( draw_vs_variant_generic );
  305.    if (vsvg == NULL)
  306.       return NULL;
  307.  
  308.    vsvg->base.key = *key;
  309.    vsvg->base.vs = vs;
  310.    vsvg->base.set_buffer    = vsvg_set_buffer;
  311.    vsvg->base.run_elts      = vsvg_run_elts;
  312.    vsvg->base.run_linear    = vsvg_run_linear;
  313.    vsvg->base.destroy       = vsvg_destroy;
  314.  
  315.    vsvg->draw = vs->draw;
  316.  
  317.    vsvg->temp_vertex_stride = MAX2(key->nr_inputs,
  318.                                    vsvg->base.vs->info.num_outputs) * 4 * sizeof(float);
  319.  
  320.    /* Build free-standing fetch and emit functions:
  321.     */
  322.    fetch.nr_elements = key->nr_inputs;
  323.    fetch.output_stride = vsvg->temp_vertex_stride;
  324.    for (i = 0; i < key->nr_inputs; i++) {
  325.       fetch.element[i].type = TRANSLATE_ELEMENT_NORMAL;
  326.       fetch.element[i].input_format = key->element[i].in.format;
  327.       fetch.element[i].input_buffer = key->element[i].in.buffer;
  328.       fetch.element[i].input_offset = key->element[i].in.offset;
  329.       fetch.element[i].instance_divisor = 0;
  330.       fetch.element[i].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
  331.       fetch.element[i].output_offset = i * 4 * sizeof(float);
  332.       assert(fetch.element[i].output_offset < fetch.output_stride);
  333.    }
  334.  
  335.  
  336.    emit.nr_elements = key->nr_outputs;
  337.    emit.output_stride = key->output_stride;
  338.    for (i = 0; i < key->nr_outputs; i++) {
  339.       if (key->element[i].out.format != EMIT_1F_PSIZE)
  340.       {      
  341.          emit.element[i].type = TRANSLATE_ELEMENT_NORMAL;
  342.          emit.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
  343.          emit.element[i].input_buffer = 0;
  344.          emit.element[i].input_offset = key->element[i].out.vs_output * 4 * sizeof(float);
  345.          emit.element[i].instance_divisor = 0;
  346.          emit.element[i].output_format = draw_translate_vinfo_format(key->element[i].out.format);
  347.          emit.element[i].output_offset = key->element[i].out.offset;
  348.          assert(emit.element[i].input_offset <= fetch.output_stride);
  349.       }
  350.       else {
  351.          emit.element[i].type = TRANSLATE_ELEMENT_NORMAL;
  352.          emit.element[i].input_format = PIPE_FORMAT_R32_FLOAT;
  353.          emit.element[i].input_buffer = 1;
  354.          emit.element[i].input_offset = 0;
  355.          emit.element[i].instance_divisor = 0;
  356.          emit.element[i].output_format = PIPE_FORMAT_R32_FLOAT;
  357.          emit.element[i].output_offset = key->element[i].out.offset;
  358.       }
  359.    }
  360.  
  361.    vsvg->fetch = draw_vs_get_fetch( vs->draw, &fetch );
  362.    vsvg->emit = draw_vs_get_emit( vs->draw, &emit );
  363.  
  364.    return &vsvg->base;
  365. }
  366.  
  367.  
  368.  
  369.  
  370.  
  371.