Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2003 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 "util/u_inlines.h"
  29. #include "util/u_math.h"
  30. #include "util/u_memory.h"
  31. #include "util/u_pstipple.h"
  32. #include "pipe/p_shader_tokens.h"
  33. #include "draw/draw_context.h"
  34. #include "draw/draw_vertex.h"
  35. #include "sp_context.h"
  36. #include "sp_screen.h"
  37. #include "sp_state.h"
  38. #include "sp_texture.h"
  39. #include "sp_tex_sample.h"
  40. #include "sp_tex_tile_cache.h"
  41.  
  42.  
  43. /**
  44.  * Mark the current vertex layout as "invalid".
  45.  * We'll validate the vertex layout later, when we start to actually
  46.  * render a point or line or tri.
  47.  */
  48. static void
  49. invalidate_vertex_layout(struct softpipe_context *softpipe)
  50. {
  51.    softpipe->vertex_info.num_attribs =  0;
  52. }
  53.  
  54.  
  55. /**
  56.  * The vertex info describes how to convert the post-transformed vertices
  57.  * (simple float[][4]) used by the 'draw' module into vertices for
  58.  * rasterization.
  59.  *
  60.  * This function validates the vertex layout and returns a pointer to a
  61.  * vertex_info object.
  62.  */
  63. struct vertex_info *
  64. softpipe_get_vertex_info(struct softpipe_context *softpipe)
  65. {
  66.    struct vertex_info *vinfo = &softpipe->vertex_info;
  67.  
  68.    if (vinfo->num_attribs == 0) {
  69.       /* compute vertex layout now */
  70.       const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
  71.       struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
  72.       const uint num = draw_num_shader_outputs(softpipe->draw);
  73.       uint i;
  74.  
  75.       /* Tell draw_vbuf to simply emit the whole post-xform vertex
  76.        * as-is.  No longer any need to try and emit draw vertex_header
  77.        * info.
  78.        */
  79.       vinfo_vbuf->num_attribs = 0;
  80.       for (i = 0; i < num; i++) {
  81.          draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
  82.       }
  83.       draw_compute_vertex_size(vinfo_vbuf);
  84.  
  85.       /*
  86.        * Loop over fragment shader inputs, searching for the matching output
  87.        * from the vertex shader.
  88.        */
  89.       vinfo->num_attribs = 0;
  90.       for (i = 0; i < fsInfo->num_inputs; i++) {
  91.          int src;
  92.          enum interp_mode interp = INTERP_LINEAR;
  93.  
  94.          switch (fsInfo->input_interpolate[i]) {
  95.          case TGSI_INTERPOLATE_CONSTANT:
  96.             interp = INTERP_CONSTANT;
  97.             break;
  98.          case TGSI_INTERPOLATE_LINEAR:
  99.             interp = INTERP_LINEAR;
  100.             break;
  101.          case TGSI_INTERPOLATE_PERSPECTIVE:
  102.             interp = INTERP_PERSPECTIVE;
  103.             break;
  104.          case TGSI_INTERPOLATE_COLOR:
  105.             assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
  106.             break;
  107.          default:
  108.             assert(0);
  109.          }
  110.  
  111.          switch (fsInfo->input_semantic_name[i]) {
  112.          case TGSI_SEMANTIC_POSITION:
  113.             interp = INTERP_POS;
  114.             break;
  115.  
  116.          case TGSI_SEMANTIC_COLOR:
  117.             if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
  118.                if (softpipe->rasterizer->flatshade)
  119.                   interp = INTERP_CONSTANT;
  120.                else
  121.                   interp = INTERP_PERSPECTIVE;
  122.             }
  123.             break;
  124.          }
  125.  
  126.          /* this includes texcoords and varying vars */
  127.          src = draw_find_shader_output(softpipe->draw,
  128.                                        fsInfo->input_semantic_name[i],
  129.                                        fsInfo->input_semantic_index[i]);
  130.          if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && src == -1)
  131.            /* try and find a bcolor */
  132.            src = draw_find_shader_output(softpipe->draw,
  133.                                          TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]);
  134.  
  135.          draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
  136.       }
  137.  
  138.       softpipe->psize_slot = draw_find_shader_output(softpipe->draw,
  139.                                                  TGSI_SEMANTIC_PSIZE, 0);
  140.       if (softpipe->psize_slot >= 0) {
  141.          draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
  142.                                softpipe->psize_slot);
  143.       }
  144.  
  145.       softpipe->layer_slot = draw_find_shader_output(softpipe->draw,
  146.                                          TGSI_SEMANTIC_LAYER, 0);
  147.       if (softpipe->layer_slot >= 0) {
  148.          draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, softpipe->layer_slot);
  149.       }
  150.  
  151.       draw_compute_vertex_size(vinfo);
  152.    }
  153.  
  154.    return vinfo;
  155. }
  156.  
  157.  
  158. /**
  159.  * Called from vbuf module.
  160.  *
  161.  * Note that there's actually two different vertex layouts in softpipe.
  162.  *
  163.  * The normal one is computed in softpipe_get_vertex_info() above and is
  164.  * used by the point/line/tri "setup" code.
  165.  *
  166.  * The other one (this one) is only used by the vbuf module (which is
  167.  * not normally used by default but used in testing).  For the vbuf module,
  168.  * we basically want to pass-through the draw module's vertex layout as-is.
  169.  * When the softpipe vbuf code begins drawing, the normal vertex layout
  170.  * will come into play again.
  171.  */
  172. struct vertex_info *
  173. softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
  174. {
  175.    (void) softpipe_get_vertex_info(softpipe);
  176.    return &softpipe->vertex_info_vbuf;
  177. }
  178.  
  179.  
  180. /**
  181.  * Recompute cliprect from scissor bounds, scissor enable and surface size.
  182.  */
  183. static void
  184. compute_cliprect(struct softpipe_context *sp)
  185. {
  186.    /* SP_NEW_FRAMEBUFFER
  187.     */
  188.    uint surfWidth = sp->framebuffer.width;
  189.    uint surfHeight = sp->framebuffer.height;
  190.  
  191.    /* SP_NEW_RASTERIZER
  192.     */
  193.    if (sp->rasterizer->scissor) {
  194.  
  195.       /* SP_NEW_SCISSOR
  196.        *
  197.        * clip to scissor rect:
  198.        */
  199.       sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
  200.       sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
  201.       sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
  202.       sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
  203.    }
  204.    else {
  205.       /* clip to surface bounds */
  206.       sp->cliprect.minx = 0;
  207.       sp->cliprect.miny = 0;
  208.       sp->cliprect.maxx = surfWidth;
  209.       sp->cliprect.maxy = surfHeight;
  210.    }
  211. }
  212.  
  213.  
  214. static void
  215. set_shader_sampler(struct softpipe_context *softpipe,
  216.                    unsigned shader,
  217.                    int max_sampler)
  218. {
  219.    int i;
  220.    for (i = 0; i <= max_sampler; i++) {
  221.       softpipe->tgsi.sampler[shader]->sp_sampler[i] =
  222.          (struct sp_sampler *)(softpipe->samplers[shader][i]);
  223.    }
  224. }
  225.  
  226. static void
  227. update_tgsi_samplers( struct softpipe_context *softpipe )
  228. {
  229.    unsigned i, sh;
  230.  
  231.    set_shader_sampler(softpipe, PIPE_SHADER_VERTEX,
  232.                       softpipe->vs->max_sampler);
  233.    set_shader_sampler(softpipe, PIPE_SHADER_FRAGMENT,
  234.                       softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]);
  235.    if (softpipe->gs) {
  236.       set_shader_sampler(softpipe, PIPE_SHADER_GEOMETRY,
  237.                          softpipe->gs->max_sampler);
  238.    }
  239.  
  240.    /* XXX is this really necessary here??? */
  241.    for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
  242.       for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
  243.          struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[sh][i];
  244.          if (tc && tc->texture) {
  245.             struct softpipe_resource *spt = softpipe_resource(tc->texture);
  246.             if (spt->timestamp != tc->timestamp) {
  247.                sp_tex_tile_cache_validate_texture( tc );
  248.                /*
  249.                  _debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
  250.                */
  251.                tc->timestamp = spt->timestamp;
  252.             }
  253.          }
  254.       }
  255.    }
  256. }
  257.  
  258.  
  259. static void
  260. update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
  261. {
  262.    struct sp_fragment_shader_variant_key key;
  263.  
  264.    memset(&key, 0, sizeof(key));
  265.  
  266.    if (prim == PIPE_PRIM_TRIANGLES)
  267.       key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
  268.  
  269.    if (softpipe->fs) {
  270.       softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
  271.                                                       softpipe->fs, &key);
  272.  
  273.       /* prepare the TGSI interpreter for FS execution */
  274.       softpipe->fs_variant->prepare(softpipe->fs_variant,
  275.                                     softpipe->fs_machine,
  276.                                     (struct tgsi_sampler *) softpipe->
  277.                                     tgsi.sampler[PIPE_SHADER_FRAGMENT]);
  278.    }
  279.    else {
  280.       softpipe->fs_variant = NULL;
  281.    }
  282.  
  283.    /* This would be the logical place to pass the fragment shader
  284.     * to the draw module.  However, doing this here, during state
  285.     * validation, causes problems with the 'draw' module helpers for
  286.     * wide/AA/stippled lines.
  287.     * In principle, the draw's fragment shader should be per-variant
  288.     * but that doesn't work.  So we use a single draw fragment shader
  289.     * per fragment shader, not per variant.
  290.     */
  291. #if 0
  292.    if (softpipe->fs_variant) {
  293.       draw_bind_fragment_shader(softpipe->draw,
  294.                                 softpipe->fs_variant->draw_shader);
  295.    }
  296.    else {
  297.       draw_bind_fragment_shader(softpipe->draw, NULL);
  298.    }
  299. #endif
  300. }
  301.  
  302.  
  303. /**
  304.  * This should be called when the polygon stipple pattern changes.
  305.  * We create a new texture from the stipple pattern and create a new
  306.  * sampler view.
  307.  */
  308. static void
  309. update_polygon_stipple_pattern(struct softpipe_context *softpipe)
  310. {
  311.    struct pipe_resource *tex;
  312.    struct pipe_sampler_view *view;
  313.  
  314.    tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
  315.                                               softpipe->poly_stipple.stipple);
  316.    pipe_resource_reference(&softpipe->pstipple.texture, tex);
  317.    pipe_resource_reference(&tex, NULL);
  318.  
  319.    view = util_pstipple_create_sampler_view(&softpipe->pipe,
  320.                                             softpipe->pstipple.texture);
  321.    pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
  322.    pipe_sampler_view_reference(&view, NULL);
  323. }
  324.  
  325.  
  326. /**
  327.  * Should be called when polygon stipple is enabled/disabled or when
  328.  * the fragment shader changes.
  329.  * We add/update the fragment sampler and sampler views to sample from
  330.  * the polygon stipple texture.  The texture unit that we use depends on
  331.  * the fragment shader (we need to use a unit not otherwise used by the
  332.  * shader).
  333.  */
  334. static void
  335. update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
  336. {
  337.    if (prim == PIPE_PRIM_TRIANGLES &&
  338.        softpipe->fs_variant->key.polygon_stipple) {
  339.       const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
  340.  
  341.       /* sampler state */
  342.       softpipe->samplers[PIPE_SHADER_FRAGMENT][unit] = softpipe->pstipple.sampler;
  343.  
  344.       /* sampler view state */
  345.       softpipe_set_sampler_views(&softpipe->pipe, PIPE_SHADER_FRAGMENT,
  346.                                  unit, 1, &softpipe->pstipple.sampler_view);
  347.  
  348.       softpipe->dirty |= SP_NEW_SAMPLER;
  349.    }
  350. }
  351.  
  352.  
  353. /* Hopefully this will remain quite simple, otherwise need to pull in
  354.  * something like the state tracker mechanism.
  355.  */
  356. void
  357. softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
  358. {
  359.    struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
  360.  
  361.    /* Check for updated textures.
  362.     */
  363.    if (softpipe->tex_timestamp != sp_screen->timestamp) {
  364.       softpipe->tex_timestamp = sp_screen->timestamp;
  365.       softpipe->dirty |= SP_NEW_TEXTURE;
  366.    }
  367.  
  368. #if DO_PSTIPPLE_IN_HELPER_MODULE
  369.    if (softpipe->dirty & SP_NEW_STIPPLE)
  370.       /* before updating samplers! */
  371.       update_polygon_stipple_pattern(softpipe);
  372. #endif
  373.  
  374.    if (softpipe->dirty & (SP_NEW_RASTERIZER |
  375.                           SP_NEW_FS))
  376.       update_fragment_shader(softpipe, prim);
  377.  
  378. #if DO_PSTIPPLE_IN_HELPER_MODULE
  379.    if (softpipe->dirty & (SP_NEW_RASTERIZER |
  380.                           SP_NEW_STIPPLE |
  381.                           SP_NEW_FS))
  382.       update_polygon_stipple_enable(softpipe, prim);
  383. #endif
  384.  
  385.    /* TODO: this looks suboptimal */
  386.    if (softpipe->dirty & (SP_NEW_SAMPLER |
  387.                           SP_NEW_TEXTURE |
  388.                           SP_NEW_FS |
  389.                           SP_NEW_VS))
  390.       update_tgsi_samplers( softpipe );
  391.  
  392.    if (softpipe->dirty & (SP_NEW_RASTERIZER |
  393.                           SP_NEW_FS |
  394.                           SP_NEW_VS))
  395.       invalidate_vertex_layout( softpipe );
  396.  
  397.    if (softpipe->dirty & (SP_NEW_SCISSOR |
  398.                           SP_NEW_RASTERIZER |
  399.                           SP_NEW_FRAMEBUFFER))
  400.       compute_cliprect(softpipe);
  401.  
  402.    if (softpipe->dirty & (SP_NEW_BLEND |
  403.                           SP_NEW_DEPTH_STENCIL_ALPHA |
  404.                           SP_NEW_FRAMEBUFFER |
  405.                           SP_NEW_STIPPLE |
  406.                           SP_NEW_FS))
  407.       sp_build_quad_pipeline(softpipe);
  408.  
  409.    softpipe->dirty = 0;
  410. }
  411.