Home | History | Annotate | Download | only in i915
      1 /**************************************************************************
      2  *
      3  * Copyright 2003 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 #include "i915_batch.h"
     29 #include "i915_state_inlines.h"
     30 #include "i915_context.h"
     31 #include "i915_reg.h"
     32 #include "i915_state.h"
     33 
     34 #include "util/u_memory.h"
     35 #include "util/u_pack_color.h"
     36 
     37 
     38 /* State that we have chosen to store in the DYNAMIC segment of the
     39  * i915 indirect state mechanism.
     40  *
     41  * Can't cache these in the way we do the static state, as there is no
     42  * start/size in the command packet, instead an 'end' value that gets
     43  * incremented.
     44  *
     45  * Additionally, there seems to be a requirement to re-issue the full
     46  * (active) state every time a 4kb boundary is crossed.
     47  */
     48 
     49 static INLINE void set_dynamic(struct i915_context *i915,
     50                                unsigned offset,
     51                                const unsigned state)
     52 {
     53    if (i915->current.dynamic[offset] == state)
     54       return;
     55 
     56    i915->current.dynamic[offset] = state;
     57    i915->dynamic_dirty |= 1 << offset;
     58    i915->hardware_dirty |= I915_HW_DYNAMIC;
     59 }
     60 
     61 
     62 
     63 static INLINE void set_dynamic_array(struct i915_context *i915,
     64                                      unsigned offset,
     65                                      const unsigned *src,
     66                                      unsigned dwords)
     67 {
     68    unsigned i;
     69 
     70    if (!memcmp(src, &i915->current.dynamic[offset], dwords * 4))
     71       return;
     72 
     73    for (i = 0; i < dwords; i++) {
     74       i915->current.dynamic[offset + i] = src[i];
     75       i915->dynamic_dirty |= 1 << (offset + i);
     76    }
     77 
     78    i915->hardware_dirty |= I915_HW_DYNAMIC;
     79 }
     80 
     81 
     82 
     83 /***********************************************************************
     84  * Modes4: stencil masks and logicop
     85  */
     86 static void upload_MODES4(struct i915_context *i915)
     87 {
     88    unsigned modes4 = 0;
     89 
     90    /* I915_NEW_STENCIL
     91     */
     92    modes4 |= i915->depth_stencil->stencil_modes4;
     93 
     94    /* I915_NEW_BLEND
     95      */
     96    modes4 |= i915->blend->modes4;
     97 
     98    set_dynamic(i915, I915_DYNAMIC_MODES4, modes4);
     99 }
    100 
    101 const struct i915_tracked_state i915_upload_MODES4 = {
    102    "MODES4",
    103    upload_MODES4,
    104    I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL
    105 };
    106 
    107 
    108 
    109 /***********************************************************************
    110  */
    111 static void upload_BFO(struct i915_context *i915)
    112 {
    113    unsigned bfo[2];
    114    bfo[0] = i915->depth_stencil->bfo[0];
    115    bfo[1] = i915->depth_stencil->bfo[1];
    116    /* I don't get it only allowed to set a ref mask when the enable bit is set? */
    117    if (bfo[0] & BFO_ENABLE_STENCIL_REF) {
    118       bfo[0] |= i915->stencil_ref.ref_value[1] << BFO_STENCIL_REF_SHIFT;
    119    }
    120 
    121    set_dynamic_array(i915, I915_DYNAMIC_BFO_0, bfo, 2);
    122 }
    123 
    124 const struct i915_tracked_state i915_upload_BFO = {
    125    "BFO",
    126    upload_BFO,
    127    I915_NEW_DEPTH_STENCIL
    128 };
    129 
    130 
    131 
    132 /***********************************************************************
    133  */
    134 static void upload_BLENDCOLOR(struct i915_context *i915)
    135 {
    136    unsigned bc[2];
    137 
    138    memset(bc, 0, sizeof(bc));
    139 
    140    /* I915_NEW_BLEND
    141     */
    142    {
    143       const float *color = i915->blend_color.color;
    144 
    145       bc[0] = _3DSTATE_CONST_BLEND_COLOR_CMD;
    146       bc[1] = pack_ui32_float4(color[0],
    147                                color[1],
    148                                color[2],
    149                                color[3]);
    150    }
    151 
    152    set_dynamic_array(i915, I915_DYNAMIC_BC_0, bc, 2);
    153 }
    154 
    155 const struct i915_tracked_state i915_upload_BLENDCOLOR = {
    156    "BLENDCOLOR",
    157    upload_BLENDCOLOR,
    158    I915_NEW_BLEND
    159 };
    160 
    161 
    162 
    163 /***********************************************************************
    164  */
    165 static void upload_IAB(struct i915_context *i915)
    166 {
    167    unsigned iab = i915->blend->iab;
    168 
    169    set_dynamic(i915, I915_DYNAMIC_IAB, iab);
    170 }
    171 
    172 const struct i915_tracked_state i915_upload_IAB = {
    173    "IAB",
    174    upload_IAB,
    175    I915_NEW_BLEND
    176 };
    177 
    178 
    179 
    180 /***********************************************************************
    181  */
    182 static void upload_DEPTHSCALE(struct i915_context *i915)
    183 {
    184    set_dynamic_array(i915, I915_DYNAMIC_DEPTHSCALE_0,
    185                      &i915->rasterizer->ds[0].u, 2);
    186 }
    187 
    188 const struct i915_tracked_state i915_upload_DEPTHSCALE = {
    189    "DEPTHSCALE",
    190    upload_DEPTHSCALE,
    191    I915_NEW_RASTERIZER
    192 };
    193 
    194 
    195 
    196 /***********************************************************************
    197  * Polygon stipple
    198  *
    199  * The i915 supports a 4x4 stipple natively, GL wants 32x32.
    200  * Fortunately stipple is usually a repeating pattern.
    201  *
    202  * XXX: does stipple pattern need to be adjusted according to
    203  * the window position?
    204  *
    205  * XXX: possibly need workaround for conform paths test.
    206  */
    207 static void upload_STIPPLE(struct i915_context *i915)
    208 {
    209    unsigned st[2];
    210 
    211    st[0] = _3DSTATE_STIPPLE;
    212    st[1] = 0;
    213 
    214    /* I915_NEW_RASTERIZER
    215     */
    216    st[1] |= i915->rasterizer->st;
    217 
    218    /* I915_NEW_STIPPLE
    219     */
    220    {
    221       const ubyte *mask = (const ubyte *)i915->poly_stipple.stipple;
    222       ubyte p[4];
    223 
    224       p[0] = mask[12] & 0xf;
    225       p[1] = mask[8] & 0xf;
    226       p[2] = mask[4] & 0xf;
    227       p[3] = mask[0] & 0xf;
    228 
    229       /* Not sure what to do about fallbacks, so for now just dont:
    230        */
    231       st[1] |= ((p[0] << 0) |
    232                 (p[1] << 4) |
    233                 (p[2] << 8) |
    234                 (p[3] << 12));
    235    }
    236 
    237    set_dynamic_array(i915, I915_DYNAMIC_STP_0, st, 2);
    238 }
    239 
    240 const struct i915_tracked_state i915_upload_STIPPLE = {
    241    "STIPPLE",
    242    upload_STIPPLE,
    243    I915_NEW_RASTERIZER | I915_NEW_STIPPLE
    244 };
    245 
    246 
    247 
    248 /***********************************************************************
    249  * Scissor enable
    250  */
    251 static void upload_SCISSOR_ENABLE( struct i915_context *i915 )
    252 {
    253    set_dynamic(i915, I915_DYNAMIC_SC_ENA_0, i915->rasterizer->sc[0]);
    254 }
    255 
    256 const struct i915_tracked_state i915_upload_SCISSOR_ENABLE = {
    257    "SCISSOR ENABLE",
    258    upload_SCISSOR_ENABLE,
    259    I915_NEW_RASTERIZER
    260 };
    261 
    262 
    263 
    264 /***********************************************************************
    265  * Scissor rect
    266  */
    267 static void upload_SCISSOR_RECT(struct i915_context *i915)
    268 {
    269    unsigned x1 = i915->scissor.minx;
    270    unsigned y1 = i915->scissor.miny;
    271    unsigned x2 = i915->scissor.maxx - 1;
    272    unsigned y2 = i915->scissor.maxy - 1;
    273    unsigned sc[3];
    274 
    275    sc[0] = _3DSTATE_SCISSOR_RECT_0_CMD;
    276    sc[1] = (y1 << 16) | (x1 & 0xffff);
    277    sc[2] = (y2 << 16) | (x2 & 0xffff);
    278 
    279    set_dynamic_array(i915, I915_DYNAMIC_SC_RECT_0, sc, 3);
    280 }
    281 
    282 const struct i915_tracked_state i915_upload_SCISSOR_RECT = {
    283    "SCISSOR RECT",
    284    upload_SCISSOR_RECT,
    285    I915_NEW_SCISSOR
    286 };
    287 
    288 
    289 
    290 /***********************************************************************
    291  */
    292 static const struct i915_tracked_state *atoms[] = {
    293    &i915_upload_MODES4,
    294    &i915_upload_BFO,
    295    &i915_upload_BLENDCOLOR,
    296    &i915_upload_IAB,
    297    &i915_upload_DEPTHSCALE,
    298    &i915_upload_STIPPLE,
    299    &i915_upload_SCISSOR_ENABLE,
    300    &i915_upload_SCISSOR_RECT
    301 };
    302 
    303 /* These will be dynamic indirect state commands, but for now just end
    304  * up on the batch buffer with everything else.
    305  */
    306 static void update_dynamic(struct i915_context *i915)
    307 {
    308    int i;
    309 
    310    for (i = 0; i < Elements(atoms); i++)
    311       if (i915->dirty & atoms[i]->dirty)
    312          atoms[i]->update(i915);
    313 }
    314 
    315 struct i915_tracked_state i915_hw_dynamic = {
    316    "dynamic",
    317    update_dynamic,
    318    ~0 /* all state atoms, becuase we do internal checking */
    319 };
    320