Home | History | Annotate | Download | only in i915
      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 #include "draw/draw_pipe.h"
     30 #include "util/u_math.h"
     31 #include "util/u_memory.h"
     32 #include "util/u_pack_color.h"
     33 
     34 #include "i915_context.h"
     35 #include "i915_reg.h"
     36 #include "i915_state.h"
     37 #include "i915_batch.h"
     38 
     39 
     40 
     41 /**
     42  * Primitive emit to hardware.  No support for vertex buffers or any
     43  * nice fast paths.
     44  */
     45 struct setup_stage {
     46    struct draw_stage stage; /**< This must be first (base class) */
     47 
     48    struct i915_context *i915;
     49 };
     50 
     51 
     52 
     53 /**
     54  * Basically a cast wrapper.
     55  */
     56 static INLINE struct setup_stage *setup_stage( struct draw_stage *stage )
     57 {
     58    return (struct setup_stage *)stage;
     59 }
     60 
     61 
     62 /**
     63  * Extract the needed fields from vertex_header and emit i915 dwords.
     64  * Recall that the vertices are constructed by the 'draw' module and
     65  * have a couple of slots at the beginning (1-dword header, 4-dword
     66  * clip pos) that we ignore here.
     67  */
     68 static INLINE void
     69 emit_hw_vertex( struct i915_context *i915,
     70                 const struct vertex_header *vertex)
     71 {
     72    const struct vertex_info *vinfo = &i915->current.vertex_info;
     73    uint i;
     74    uint count = 0;  /* for debug/sanity */
     75 
     76    assert(!i915->dirty);
     77 
     78    for (i = 0; i < vinfo->num_attribs; i++) {
     79       const uint j = vinfo->attrib[i].src_index;
     80       const float *attrib = vertex->data[j];
     81       switch (vinfo->attrib[i].emit) {
     82       case EMIT_1F:
     83          OUT_BATCH( fui(attrib[0]) );
     84          count++;
     85          break;
     86       case EMIT_2F:
     87          OUT_BATCH( fui(attrib[0]) );
     88          OUT_BATCH( fui(attrib[1]) );
     89          count += 2;
     90          break;
     91       case EMIT_3F:
     92          OUT_BATCH( fui(attrib[0]) );
     93          OUT_BATCH( fui(attrib[1]) );
     94          OUT_BATCH( fui(attrib[2]) );
     95          count += 3;
     96          break;
     97       case EMIT_4F:
     98          OUT_BATCH( fui(attrib[0]) );
     99          OUT_BATCH( fui(attrib[1]) );
    100          OUT_BATCH( fui(attrib[2]) );
    101          OUT_BATCH( fui(attrib[3]) );
    102          count += 4;
    103          break;
    104       case EMIT_4UB:
    105          OUT_BATCH( pack_ub4(float_to_ubyte( attrib[0] ),
    106                              float_to_ubyte( attrib[1] ),
    107                              float_to_ubyte( attrib[2] ),
    108                              float_to_ubyte( attrib[3] )) );
    109          count += 1;
    110          break;
    111       case EMIT_4UB_BGRA:
    112          OUT_BATCH( pack_ub4(float_to_ubyte( attrib[2] ),
    113                              float_to_ubyte( attrib[1] ),
    114                              float_to_ubyte( attrib[0] ),
    115                              float_to_ubyte( attrib[3] )) );
    116          count += 1;
    117          break;
    118       default:
    119          assert(0);
    120       }
    121    }
    122    assert(count == vinfo->size);
    123 }
    124 
    125 
    126 
    127 static INLINE void
    128 emit_prim( struct draw_stage *stage,
    129 	   struct prim_header *prim,
    130 	   unsigned hwprim,
    131 	   unsigned nr )
    132 {
    133    struct i915_context *i915 = setup_stage(stage)->i915;
    134    unsigned vertex_size;
    135    unsigned i;
    136 
    137    if (i915->dirty)
    138       i915_update_derived( i915 );
    139 
    140    if (i915->hardware_dirty)
    141       i915_emit_hardware_state( i915 );
    142 
    143    /* need to do this after validation! */
    144    vertex_size = i915->current.vertex_info.size * 4; /* in bytes */
    145    assert(vertex_size >= 12); /* never smaller than 12 bytes */
    146 
    147    if (!BEGIN_BATCH( 1 + nr * vertex_size / 4)) {
    148       FLUSH_BATCH(NULL);
    149 
    150       /* Make sure state is re-emitted after a flush:
    151        */
    152       i915_emit_hardware_state( i915 );
    153 
    154       if (!BEGIN_BATCH( 1 + nr * vertex_size / 4)) {
    155 	 assert(0);
    156 	 return;
    157       }
    158    }
    159 
    160    /* Emit each triangle as a single primitive.  I told you this was
    161     * simple.
    162     */
    163    OUT_BATCH(_3DPRIMITIVE |
    164 	     hwprim |
    165 	     ((4 + vertex_size * nr)/4 - 2));
    166 
    167    for (i = 0; i < nr; i++)
    168       emit_hw_vertex(i915, prim->v[i]);
    169 }
    170 
    171 
    172 static void
    173 setup_tri( struct draw_stage *stage, struct prim_header *prim )
    174 {
    175    emit_prim( stage, prim, PRIM3D_TRILIST, 3 );
    176 }
    177 
    178 
    179 static void
    180 setup_line(struct draw_stage *stage, struct prim_header *prim)
    181 {
    182    emit_prim( stage, prim, PRIM3D_LINELIST, 2 );
    183 }
    184 
    185 
    186 static void
    187 setup_point(struct draw_stage *stage, struct prim_header *prim)
    188 {
    189    emit_prim( stage, prim, PRIM3D_POINTLIST, 1 );
    190 }
    191 
    192 
    193 static void setup_flush( struct draw_stage *stage, unsigned flags )
    194 {
    195 }
    196 
    197 static void reset_stipple_counter( struct draw_stage *stage )
    198 {
    199 }
    200 
    201 static void render_destroy( struct draw_stage *stage )
    202 {
    203    FREE( stage );
    204 }
    205 
    206 
    207 /**
    208  * Create a new primitive setup/render stage.  This gets plugged into
    209  * the 'draw' module's pipeline.
    210  */
    211 struct draw_stage *i915_draw_render_stage( struct i915_context *i915 )
    212 {
    213    struct setup_stage *setup = CALLOC_STRUCT(setup_stage);
    214 
    215    setup->i915 = i915;
    216    setup->stage.draw = i915->draw;
    217    setup->stage.point = setup_point;
    218    setup->stage.line = setup_line;
    219    setup->stage.tri = setup_tri;
    220    setup->stage.flush = setup_flush;
    221    setup->stage.reset_stipple_counter = reset_stipple_counter;
    222    setup->stage.destroy = render_destroy;
    223 
    224    return &setup->stage;
    225 }
    226