Home | History | Annotate | Download | only in i965
      1 /*
      2  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
      3  Intel funded Tungsten Graphics to
      4  develop this 3D driver.
      5 
      6  Permission is hereby granted, free of charge, to any person obtaining
      7  a 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, sublicense, 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
     16  portions of the Software.
     17 
     18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     21  IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     22  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     23  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     24  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25 
     26  **********************************************************************/
     27  /*
     28   * Authors:
     29   *   Keith Whitwell <keithw (at) vmware.com>
     30   */
     31 
     32 #include "compiler/nir/nir.h"
     33 #include "main/macros.h"
     34 #include "main/mtypes.h"
     35 #include "main/enums.h"
     36 #include "main/fbobject.h"
     37 
     38 #include "intel_batchbuffer.h"
     39 
     40 #include "brw_defines.h"
     41 #include "brw_context.h"
     42 #include "brw_eu.h"
     43 #include "brw_util.h"
     44 #include "brw_sf.h"
     45 #include "brw_state.h"
     46 
     47 #include "util/ralloc.h"
     48 
     49 static void compile_sf_prog( struct brw_context *brw,
     50 			     struct brw_sf_prog_key *key )
     51 {
     52    struct brw_sf_compile c;
     53    const GLuint *program;
     54    void *mem_ctx;
     55    GLuint program_size;
     56 
     57    memset(&c, 0, sizeof(c));
     58 
     59    mem_ctx = ralloc_context(NULL);
     60    /* Begin the compilation:
     61     */
     62    brw_init_codegen(&brw->screen->devinfo, &c.func, mem_ctx);
     63 
     64    c.key = *key;
     65    c.vue_map = brw->vue_map_geom_out;
     66    if (c.key.do_point_coord) {
     67       /*
     68        * gl_PointCoord is a FS instead of VS builtin variable, thus it's
     69        * not included in c.vue_map generated in VS stage. Here we add
     70        * it manually to let SF shader generate the needed interpolation
     71        * coefficient for FS shader.
     72        */
     73       c.vue_map.varying_to_slot[BRW_VARYING_SLOT_PNTC] = c.vue_map.num_slots;
     74       c.vue_map.slot_to_varying[c.vue_map.num_slots++] = BRW_VARYING_SLOT_PNTC;
     75    }
     76    c.urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET;
     77    c.nr_attr_regs = (c.vue_map.num_slots + 1)/2 - c.urb_entry_read_offset;
     78    c.nr_setup_regs = c.nr_attr_regs;
     79 
     80    c.prog_data.urb_read_length = c.nr_attr_regs;
     81    c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
     82 
     83    /* Which primitive?  Or all three?
     84     */
     85    switch (key->primitive) {
     86    case SF_TRIANGLES:
     87       c.nr_verts = 3;
     88       brw_emit_tri_setup( &c, true );
     89       break;
     90    case SF_LINES:
     91       c.nr_verts = 2;
     92       brw_emit_line_setup( &c, true );
     93       break;
     94    case SF_POINTS:
     95       c.nr_verts = 1;
     96       if (key->do_point_sprite)
     97 	  brw_emit_point_sprite_setup( &c, true );
     98       else
     99 	  brw_emit_point_setup( &c, true );
    100       break;
    101    case SF_UNFILLED_TRIS:
    102       c.nr_verts = 3;
    103       brw_emit_anyprim_setup( &c );
    104       break;
    105    default:
    106       unreachable("not reached");
    107    }
    108 
    109    /* FINISHME: SF programs use calculated jumps (i.e., JMPI with a register
    110     * source). Compacting would be difficult.
    111     */
    112    /* brw_compact_instructions(&c.func, 0, 0, NULL); */
    113 
    114    /* get the program
    115     */
    116    program = brw_get_program(&c.func, &program_size);
    117 
    118    if (unlikely(INTEL_DEBUG & DEBUG_SF)) {
    119       fprintf(stderr, "sf:\n");
    120       brw_disassemble(&brw->screen->devinfo,
    121                       c.func.store, 0, program_size, stderr);
    122       fprintf(stderr, "\n");
    123    }
    124 
    125    brw_upload_cache(&brw->cache, BRW_CACHE_SF_PROG,
    126 		    &c.key, sizeof(c.key),
    127 		    program, program_size,
    128 		    &c.prog_data, sizeof(c.prog_data),
    129 		    &brw->sf.prog_offset, &brw->sf.prog_data);
    130    ralloc_free(mem_ctx);
    131 }
    132 
    133 /* Calculate interpolants for triangle and line rasterization.
    134  */
    135 void
    136 brw_upload_sf_prog(struct brw_context *brw)
    137 {
    138    struct gl_context *ctx = &brw->ctx;
    139    struct brw_sf_prog_key key;
    140 
    141    if (!brw_state_dirty(brw,
    142                         _NEW_BUFFERS |
    143                         _NEW_HINT |
    144                         _NEW_LIGHT |
    145                         _NEW_POINT |
    146                         _NEW_POLYGON |
    147                         _NEW_PROGRAM |
    148                         _NEW_TRANSFORM,
    149                         BRW_NEW_BLORP |
    150                         BRW_NEW_FS_PROG_DATA |
    151                         BRW_NEW_REDUCED_PRIMITIVE |
    152                         BRW_NEW_VUE_MAP_GEOM_OUT))
    153       return;
    154 
    155    /* _NEW_BUFFERS */
    156    bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);
    157 
    158    memset(&key, 0, sizeof(key));
    159 
    160    /* Populate the key, noting state dependencies:
    161     */
    162    /* BRW_NEW_VUE_MAP_GEOM_OUT */
    163    key.attrs = brw->vue_map_geom_out.slots_valid;
    164 
    165    /* BRW_NEW_REDUCED_PRIMITIVE */
    166    switch (brw->reduced_primitive) {
    167    case GL_TRIANGLES:
    168       /* NOTE: We just use the edgeflag attribute as an indicator that
    169        * unfilled triangles are active.  We don't actually do the
    170        * edgeflag testing here, it is already done in the clip
    171        * program.
    172        */
    173       if (key.attrs & BITFIELD64_BIT(VARYING_SLOT_EDGE))
    174 	 key.primitive = SF_UNFILLED_TRIS;
    175       else
    176 	 key.primitive = SF_TRIANGLES;
    177       break;
    178    case GL_LINES:
    179       key.primitive = SF_LINES;
    180       break;
    181    case GL_POINTS:
    182       key.primitive = SF_POINTS;
    183       break;
    184    }
    185 
    186    /* _NEW_TRANSFORM */
    187    key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0);
    188 
    189    /* _NEW_POINT */
    190    key.do_point_sprite = ctx->Point.PointSprite;
    191    if (key.do_point_sprite) {
    192       key.point_sprite_coord_replace = ctx->Point.CoordReplace & 0xff;
    193    }
    194    if (brw->fragment_program->info.inputs_read &
    195        BITFIELD64_BIT(VARYING_SLOT_PNTC)) {
    196       key.do_point_coord = 1;
    197    }
    198 
    199    /*
    200     * Window coordinates in a FBO are inverted, which means point
    201     * sprite origin must be inverted, too.
    202     */
    203    if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo)
    204       key.sprite_origin_lower_left = true;
    205 
    206    /* BRW_NEW_FS_PROG_DATA */
    207    const struct brw_wm_prog_data *wm_prog_data =
    208       brw_wm_prog_data(brw->wm.base.prog_data);
    209    if (wm_prog_data) {
    210       key.contains_flat_varying = wm_prog_data->contains_flat_varying;
    211       key.interp_mode = wm_prog_data->interp_mode;
    212    }
    213 
    214    /* _NEW_LIGHT | _NEW_PROGRAM */
    215    key.do_twoside_color = ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||
    216                            ctx->VertexProgram._TwoSideEnabled);
    217 
    218    /* _NEW_POLYGON */
    219    if (key.do_twoside_color) {
    220       /* If we're rendering to a FBO, we have to invert the polygon
    221        * face orientation, just as we invert the viewport in
    222        * sf_unit_create_from_key().
    223        */
    224       key.frontface_ccw = ctx->Polygon._FrontBit == render_to_fbo;
    225    }
    226 
    227    if (!brw_search_cache(&brw->cache, BRW_CACHE_SF_PROG,
    228 			 &key, sizeof(key),
    229 			 &brw->sf.prog_offset, &brw->sf.prog_data)) {
    230       compile_sf_prog( brw, &key );
    231    }
    232 }
    233