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 
     33 #include "brw_context.h"
     34 #include "brw_state.h"
     35 #include "brw_defines.h"
     36 #include "brw_util.h"
     37 #include "main/macros.h"
     38 #include "main/stencil.h"
     39 #include "intel_batchbuffer.h"
     40 
     41 static void
     42 brw_upload_cc_vp(struct brw_context *brw)
     43 {
     44    struct gl_context *ctx = &brw->ctx;
     45    struct brw_cc_viewport *ccv;
     46 
     47    /* BRW_NEW_VIEWPORT_COUNT */
     48    const unsigned viewport_count = brw->clip.viewport_count;
     49 
     50    ccv = brw_state_batch(brw, AUB_TRACE_CC_VP_STATE,
     51 			 sizeof(*ccv) * viewport_count, 32,
     52                          &brw->cc.vp_offset);
     53 
     54    /* _NEW_TRANSFORM */
     55    for (unsigned i = 0; i < viewport_count; i++) {
     56       if (ctx->Transform.DepthClamp) {
     57          /* _NEW_VIEWPORT */
     58          ccv[i].min_depth = MIN2(ctx->ViewportArray[i].Near,
     59                                  ctx->ViewportArray[i].Far);
     60          ccv[i].max_depth = MAX2(ctx->ViewportArray[i].Near,
     61                                  ctx->ViewportArray[i].Far);
     62       } else {
     63          ccv[i].min_depth = 0.0;
     64          ccv[i].max_depth = 1.0;
     65       }
     66    }
     67 
     68    if (brw->gen >= 7) {
     69       BEGIN_BATCH(2);
     70       OUT_BATCH(_3DSTATE_VIEWPORT_STATE_POINTERS_CC << 16 | (2 - 2));
     71       OUT_BATCH(brw->cc.vp_offset);
     72       ADVANCE_BATCH();
     73    } else {
     74       brw->ctx.NewDriverState |= BRW_NEW_CC_VP;
     75    }
     76 }
     77 
     78 const struct brw_tracked_state brw_cc_vp = {
     79    .dirty = {
     80       .mesa = _NEW_TRANSFORM |
     81               _NEW_VIEWPORT,
     82       .brw = BRW_NEW_BATCH |
     83              BRW_NEW_BLORP |
     84              BRW_NEW_VIEWPORT_COUNT,
     85    },
     86    .emit = brw_upload_cc_vp
     87 };
     88 
     89 /**
     90  * Modify blend function to force destination alpha to 1.0
     91  *
     92  * If \c function specifies a blend function that uses destination alpha,
     93  * replace it with a function that hard-wires destination alpha to 1.0.  This
     94  * is used when rendering to xRGB targets.
     95  */
     96 GLenum
     97 brw_fix_xRGB_alpha(GLenum function)
     98 {
     99    switch (function) {
    100    case GL_DST_ALPHA:
    101       return GL_ONE;
    102 
    103    case GL_ONE_MINUS_DST_ALPHA:
    104    case GL_SRC_ALPHA_SATURATE:
    105       return GL_ZERO;
    106    }
    107 
    108    return function;
    109 }
    110 
    111 /**
    112  * Creates a CC unit packet from the current blend state.
    113  */
    114 static void upload_cc_unit(struct brw_context *brw)
    115 {
    116    struct gl_context *ctx = &brw->ctx;
    117    struct brw_cc_unit_state *cc;
    118 
    119    cc = brw_state_batch(brw, AUB_TRACE_CC_STATE,
    120 			sizeof(*cc), 64, &brw->cc.state_offset);
    121    memset(cc, 0, sizeof(*cc));
    122 
    123    /* _NEW_STENCIL | _NEW_BUFFERS */
    124    if (ctx->Stencil._Enabled) {
    125       const unsigned back = ctx->Stencil._BackFace;
    126 
    127       cc->cc0.stencil_enable = 1;
    128       cc->cc0.stencil_func =
    129 	 intel_translate_compare_func(ctx->Stencil.Function[0]);
    130       cc->cc0.stencil_fail_op =
    131 	 intel_translate_stencil_op(ctx->Stencil.FailFunc[0]);
    132       cc->cc0.stencil_pass_depth_fail_op =
    133 	 intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]);
    134       cc->cc0.stencil_pass_depth_pass_op =
    135 	 intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]);
    136       cc->cc1.stencil_ref = _mesa_get_stencil_ref(ctx, 0);
    137       cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0];
    138       cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0];
    139 
    140       if (ctx->Stencil._TestTwoSide) {
    141 	 cc->cc0.bf_stencil_enable = 1;
    142 	 cc->cc0.bf_stencil_func =
    143 	    intel_translate_compare_func(ctx->Stencil.Function[back]);
    144 	 cc->cc0.bf_stencil_fail_op =
    145 	    intel_translate_stencil_op(ctx->Stencil.FailFunc[back]);
    146 	 cc->cc0.bf_stencil_pass_depth_fail_op =
    147 	    intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]);
    148 	 cc->cc0.bf_stencil_pass_depth_pass_op =
    149 	    intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]);
    150 	 cc->cc1.bf_stencil_ref = _mesa_get_stencil_ref(ctx, back);
    151 	 cc->cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back];
    152 	 cc->cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back];
    153       }
    154 
    155       /* Not really sure about this:
    156        */
    157       if (ctx->Stencil.WriteMask[0] ||
    158 	  (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back]))
    159 	 cc->cc0.stencil_write_enable = 1;
    160    }
    161 
    162    /* _NEW_COLOR */
    163    if (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY) {
    164       cc->cc2.logicop_enable = 1;
    165       cc->cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp);
    166    } else if (ctx->Color.BlendEnabled && !ctx->Color._AdvancedBlendMode) {
    167       GLenum eqRGB = ctx->Color.Blend[0].EquationRGB;
    168       GLenum eqA = ctx->Color.Blend[0].EquationA;
    169       GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
    170       GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
    171       GLenum srcA = ctx->Color.Blend[0].SrcA;
    172       GLenum dstA = ctx->Color.Blend[0].DstA;
    173 
    174       /* If the renderbuffer is XRGB, we have to frob the blend function to
    175        * force the destination alpha to 1.0.  This means replacing GL_DST_ALPHA
    176        * with GL_ONE and GL_ONE_MINUS_DST_ALPHA with GL_ZERO.
    177        */
    178       if (ctx->DrawBuffer->Visual.alphaBits == 0) {
    179 	 srcRGB = brw_fix_xRGB_alpha(srcRGB);
    180 	 srcA   = brw_fix_xRGB_alpha(srcA);
    181 	 dstRGB = brw_fix_xRGB_alpha(dstRGB);
    182 	 dstA   = brw_fix_xRGB_alpha(dstA);
    183       }
    184 
    185       if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
    186 	 srcRGB = dstRGB = GL_ONE;
    187       }
    188 
    189       if (eqA == GL_MIN || eqA == GL_MAX) {
    190 	 srcA = dstA = GL_ONE;
    191       }
    192 
    193       cc->cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB);
    194       cc->cc6.src_blend_factor = brw_translate_blend_factor(srcRGB);
    195       cc->cc6.blend_function = brw_translate_blend_equation(eqRGB);
    196 
    197       cc->cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
    198       cc->cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA);
    199       cc->cc5.ia_blend_function = brw_translate_blend_equation(eqA);
    200 
    201       cc->cc3.blend_enable = 1;
    202       cc->cc3.ia_blend_enable = (srcA != srcRGB ||
    203 				dstA != dstRGB ||
    204 				eqA != eqRGB);
    205    }
    206 
    207    /* _NEW_BUFFERS */
    208    if (ctx->Color.AlphaEnabled && ctx->DrawBuffer->_NumColorDrawBuffers <= 1) {
    209       cc->cc3.alpha_test = 1;
    210       cc->cc3.alpha_test_func =
    211 	 intel_translate_compare_func(ctx->Color.AlphaFunc);
    212       cc->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
    213 
    214       UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef);
    215    }
    216 
    217    if (ctx->Color.DitherFlag) {
    218       cc->cc5.dither_enable = 1;
    219       cc->cc6.y_dither_offset = 0;
    220       cc->cc6.x_dither_offset = 0;
    221    }
    222 
    223    /* _NEW_DEPTH */
    224    if (ctx->Depth.Test) {
    225       cc->cc2.depth_test = 1;
    226       cc->cc2.depth_test_function =
    227 	 intel_translate_compare_func(ctx->Depth.Func);
    228       cc->cc2.depth_write_enable = brw_depth_writes_enabled(brw);
    229    }
    230 
    231    if (brw->stats_wm || unlikely(INTEL_DEBUG & DEBUG_STATS))
    232       cc->cc5.statistics_enable = 1;
    233 
    234    /* BRW_NEW_CC_VP */
    235    cc->cc4.cc_viewport_state_offset = (brw->batch.bo->offset64 +
    236 				       brw->cc.vp_offset) >> 5; /* reloc */
    237 
    238    brw->ctx.NewDriverState |= BRW_NEW_GEN4_UNIT_STATE;
    239 
    240    /* Emit CC viewport relocation */
    241    drm_intel_bo_emit_reloc(brw->batch.bo,
    242 			   (brw->cc.state_offset +
    243 			    offsetof(struct brw_cc_unit_state, cc4)),
    244 			   brw->batch.bo, brw->cc.vp_offset,
    245 			   I915_GEM_DOMAIN_INSTRUCTION, 0);
    246 }
    247 
    248 const struct brw_tracked_state brw_cc_unit = {
    249    .dirty = {
    250       .mesa = _NEW_BUFFERS |
    251               _NEW_COLOR |
    252               _NEW_DEPTH |
    253               _NEW_STENCIL,
    254       .brw = BRW_NEW_BATCH |
    255              BRW_NEW_BLORP |
    256              BRW_NEW_CC_VP |
    257              BRW_NEW_STATS_WM,
    258    },
    259    .emit = upload_cc_unit,
    260 };
    261 
    262 static void upload_blend_constant_color(struct brw_context *brw)
    263 {
    264    struct gl_context *ctx = &brw->ctx;
    265 
    266    BEGIN_BATCH(5);
    267    OUT_BATCH(_3DSTATE_BLEND_CONSTANT_COLOR << 16 | (5-2));
    268    OUT_BATCH_F(ctx->Color.BlendColorUnclamped[0]);
    269    OUT_BATCH_F(ctx->Color.BlendColorUnclamped[1]);
    270    OUT_BATCH_F(ctx->Color.BlendColorUnclamped[2]);
    271    OUT_BATCH_F(ctx->Color.BlendColorUnclamped[3]);
    272    ADVANCE_BATCH();
    273 }
    274 
    275 const struct brw_tracked_state brw_blend_constant_color = {
    276    .dirty = {
    277       .mesa = _NEW_COLOR,
    278       .brw = BRW_NEW_CONTEXT |
    279              BRW_NEW_BLORP,
    280    },
    281    .emit = upload_blend_constant_color
    282 };
    283