/** * Apply stencil test to an array of stencil values (before depth buffering). * For the values that fail, we'll apply the GL_STENCIL_FAIL operator to * the stencil values. * * @param face 0 or 1 for front or back-face polygons * @param n number of pixels in the array * @param stencil array of [n] stencil values (in/out) * @param mask array [n] of flag: 0=skip the pixel, 1=stencil the pixel, * values are set to zero where the stencil test fails. * @param stride stride between stencil values * @return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. */ static GLboolean do_stencil_test(struct gl_context *ctx, GLuint face, GLuint n, GLubyte stencil[], GLubyte mask[], GLint stride) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLubyte *fail = swrast->stencil_temp.buf2; GLboolean allfail = GL_FALSE; GLuint i, j; const GLuint valueMask = ctx->Stencil.ValueMask[face]; const GLubyte ref = (GLubyte) (_mesa_get_stencil_ref(ctx, face) & valueMask); GLubyte s; /* * Perform stencil test. The results of this operation are stored * in the fail[] array: * IF fail[i] is non-zero THEN * the stencil fail operator is to be applied * ELSE * the stencil fail operator is not to be applied * ENDIF */ switch (ctx->Stencil.Function[face]) { case GL_NEVER: STENCIL_TEST(0); allfail = GL_TRUE; break; case GL_LESS: STENCIL_TEST(ref < s); break; case GL_LEQUAL: STENCIL_TEST(ref <= s); break; case GL_GREATER: STENCIL_TEST(ref > s); break; case GL_GEQUAL: STENCIL_TEST(ref >= s); break; case GL_EQUAL: STENCIL_TEST(ref == s); break; case GL_NOTEQUAL: STENCIL_TEST(ref != s); break; case GL_ALWAYS: STENCIL_TEST(1); break; default: _mesa_problem(ctx, "Bad stencil func in gl_stencil_span"); return 0; } if (ctx->Stencil.FailFunc[face] != GL_KEEP) { apply_stencil_op(ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail, stride); } return !allfail; }
static void gen6_upload_color_calc_state(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct gen6_color_calc_state *cc; cc = brw_state_batch(brw, AUB_TRACE_CC_STATE, sizeof(*cc), 64, &brw->cc.state_offset); memset(cc, 0, sizeof(*cc)); /* _NEW_COLOR */ cc->cc0.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; UNCLAMPED_FLOAT_TO_UBYTE(cc->cc1.alpha_ref_fi.ui, ctx->Color.AlphaRef); if (brw->gen < 9) { /* _NEW_STENCIL */ cc->cc0.stencil_ref = _mesa_get_stencil_ref(ctx, 0); cc->cc0.bf_stencil_ref = _mesa_get_stencil_ref(ctx, ctx->Stencil._BackFace); } /* _NEW_COLOR */ cc->constant_r = ctx->Color.BlendColorUnclamped[0]; cc->constant_g = ctx->Color.BlendColorUnclamped[1]; cc->constant_b = ctx->Color.BlendColorUnclamped[2]; cc->constant_a = ctx->Color.BlendColorUnclamped[3]; /* Point the GPU at the new indirect state. */ if (brw->gen == 6) { BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(brw->cc.state_offset | 1); ADVANCE_BATCH(); } else { BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (2 - 2)); OUT_BATCH(brw->cc.state_offset | 1); ADVANCE_BATCH(); } }
/** * Apply the given stencil operator to the array of stencil values. * Don't touch stencil[i] if mask[i] is zero. * @param n number of stencil values * @param oper the stencil buffer operator * @param face 0 or 1 for front or back face operation * @param stencil array of stencil values (in/out) * @param mask array [n] of flag: 1=apply operator, 0=don't apply operator * @param stride stride between stencil values */ static void apply_stencil_op(const struct gl_context *ctx, GLenum oper, GLuint face, GLuint n, GLubyte stencil[], const GLubyte mask[], GLint stride) { const GLubyte ref = _mesa_get_stencil_ref(ctx, face); const GLubyte wrtmask = ctx->Stencil.WriteMask[face]; const GLubyte invmask = (GLubyte) (~wrtmask); GLuint i, j; switch (oper) { case GL_KEEP: /* do nothing */ break; case GL_ZERO: /* replace stencil buf values with zero */ STENCIL_OP(0); break; case GL_REPLACE: /* replace stencil buf values with ref value */ STENCIL_OP(ref); break; case GL_INCR: /* increment stencil buf values, with clamping */ STENCIL_OP(clamp(s + 1)); break; case GL_DECR: /* increment stencil buf values, with clamping */ STENCIL_OP(clamp(s - 1)); break; case GL_INCR_WRAP_EXT: /* increment stencil buf values, without clamping */ STENCIL_OP(s + 1); break; case GL_DECR_WRAP_EXT: /* increment stencil buf values, without clamping */ STENCIL_OP(s - 1); break; case GL_INVERT: /* replace stencil buf values with inverted value */ STENCIL_OP(~s); break; default: _mesa_problem(ctx, "Bad stencil op in apply_stencil_op"); } }
void nv04_emit_control(struct gl_context *ctx, int emit) { struct nv04_context *nv04 = to_nv04_context(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; int cull = ctx->Polygon.CullFaceMode; int front = ctx->Polygon.FrontFace; nv04->ctrl[0] = NV04_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_FIXED | NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN_CORNER; nv04->ctrl[1] = 0; nv04->ctrl[2] = 0; /* Dithering. */ if (ctx->Color.DitherFlag) nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE; /* Cull mode. */ if (!ctx->Polygon.CullFlag) nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_NONE; else if (cull == GL_FRONT_AND_BACK) nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_BOTH; else nv04->ctrl[0] |= (cull == GL_FRONT) ^ (front == GL_CCW) ? NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CW : NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CCW; /* Depth test. */ if (ctx->Depth.Test && fb->Visual.depthBits > 0) nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE; if (ctx->Depth.Mask && fb->Visual.depthBits > 0) nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE; nv04->ctrl[0] |= get_comparison_op(ctx->Depth.Func) << 16; /* Alpha test. */ if (ctx->Color.AlphaEnabled) nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE; nv04->ctrl[0] |= get_comparison_op(ctx->Color.AlphaFunc) << 8 | FLOAT_TO_UBYTE(ctx->Color.AlphaRef); /* Color mask. */ if (ctx->Color.ColorMask[0][RCOMP]) nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE; if (ctx->Color.ColorMask[0][GCOMP]) nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE; if (ctx->Color.ColorMask[0][BCOMP]) nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE; if (ctx->Color.ColorMask[0][ACOMP]) nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE; /* Stencil test. */ if (ctx->Stencil.WriteMask[0]) nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE; if (_mesa_stencil_is_enabled(ctx)) nv04->ctrl[1] |= NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE; nv04->ctrl[1] |= get_comparison_op(ctx->Stencil.Function[0]) << 4 | _mesa_get_stencil_ref(ctx, 0) << 8 | ctx->Stencil.ValueMask[0] << 16 | ctx->Stencil.WriteMask[0] << 24; nv04->ctrl[2] |= get_stencil_op(ctx->Stencil.ZPassFunc[0]) << 8 | get_stencil_op(ctx->Stencil.ZFailFunc[0]) << 4 | get_stencil_op(ctx->Stencil.FailFunc[0]); }
/** * Creates the state cache entry for the given CC unit key. */ static void upload_cc_unit(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_cc_unit_state *cc; cc = brw_state_batch(brw, AUB_TRACE_CC_STATE, sizeof(*cc), 64, &brw->cc.state_offset); memset(cc, 0, sizeof(*cc)); /* _NEW_STENCIL | _NEW_BUFFERS */ if (ctx->Stencil._Enabled) { const unsigned back = ctx->Stencil._BackFace; cc->cc0.stencil_enable = 1; cc->cc0.stencil_func = intel_translate_compare_func(ctx->Stencil.Function[0]); cc->cc0.stencil_fail_op = intel_translate_stencil_op(ctx->Stencil.FailFunc[0]); cc->cc0.stencil_pass_depth_fail_op = intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]); cc->cc0.stencil_pass_depth_pass_op = intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]); cc->cc1.stencil_ref = _mesa_get_stencil_ref(ctx, 0); cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0]; cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0]; if (ctx->Stencil._TestTwoSide) { cc->cc0.bf_stencil_enable = 1; cc->cc0.bf_stencil_func = intel_translate_compare_func(ctx->Stencil.Function[back]); cc->cc0.bf_stencil_fail_op = intel_translate_stencil_op(ctx->Stencil.FailFunc[back]); cc->cc0.bf_stencil_pass_depth_fail_op = intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]); cc->cc0.bf_stencil_pass_depth_pass_op = intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]); cc->cc1.bf_stencil_ref = _mesa_get_stencil_ref(ctx, back); cc->cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back]; cc->cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back]; } /* Not really sure about this: */ if (ctx->Stencil.WriteMask[0] || (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back])) cc->cc0.stencil_write_enable = 1; } /* _NEW_COLOR */ if (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY) { cc->cc2.logicop_enable = 1; cc->cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp); } else if (ctx->Color.BlendEnabled) { GLenum eqRGB = ctx->Color.Blend[0].EquationRGB; GLenum eqA = ctx->Color.Blend[0].EquationA; GLenum srcRGB = ctx->Color.Blend[0].SrcRGB; GLenum dstRGB = ctx->Color.Blend[0].DstRGB; GLenum srcA = ctx->Color.Blend[0].SrcA; GLenum dstA = ctx->Color.Blend[0].DstA; /* If the renderbuffer is XRGB, we have to frob the blend function to * force the destination alpha to 1.0. This means replacing GL_DST_ALPHA * with GL_ONE and GL_ONE_MINUS_DST_ALPHA with GL_ZERO. */ if (ctx->DrawBuffer->Visual.alphaBits == 0) { srcRGB = brw_fix_xRGB_alpha(srcRGB); srcA = brw_fix_xRGB_alpha(srcA); dstRGB = brw_fix_xRGB_alpha(dstRGB); dstA = brw_fix_xRGB_alpha(dstA); } if (eqRGB == GL_MIN || eqRGB == GL_MAX) { srcRGB = dstRGB = GL_ONE; } if (eqA == GL_MIN || eqA == GL_MAX) { srcA = dstA = GL_ONE; } cc->cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB); cc->cc6.src_blend_factor = brw_translate_blend_factor(srcRGB); cc->cc6.blend_function = brw_translate_blend_equation(eqRGB); cc->cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA); cc->cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA); cc->cc5.ia_blend_function = brw_translate_blend_equation(eqA); cc->cc3.blend_enable = 1; cc->cc3.ia_blend_enable = (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB); } /* _NEW_BUFFERS */ if (ctx->Color.AlphaEnabled && ctx->DrawBuffer->_NumColorDrawBuffers <= 1) { cc->cc3.alpha_test = 1; cc->cc3.alpha_test_func = intel_translate_compare_func(ctx->Color.AlphaFunc); cc->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef); } if (ctx->Color.DitherFlag) { cc->cc5.dither_enable = 1; cc->cc6.y_dither_offset = 0; cc->cc6.x_dither_offset = 0; } /* _NEW_DEPTH */ if (ctx->Depth.Test) { cc->cc2.depth_test = 1; cc->cc2.depth_test_function = intel_translate_compare_func(ctx->Depth.Func); cc->cc2.depth_write_enable = ctx->Depth.Mask; } if (brw->stats_wm || unlikely(INTEL_DEBUG & DEBUG_STATS)) cc->cc5.statistics_enable = 1; /* CACHE_NEW_CC_VP */ cc->cc4.cc_viewport_state_offset = (brw->batch.bo->offset + brw->cc.vp_offset) >> 5; /* reloc */ brw->state.dirty.cache |= CACHE_NEW_CC_UNIT; /* Emit CC viewport relocation */ drm_intel_bo_emit_reloc(brw->batch.bo, (brw->cc.state_offset + offsetof(struct brw_cc_unit_state, cc4)), brw->batch.bo, brw->cc.vp_offset, I915_GEM_DOMAIN_INSTRUCTION, 0); }
static void update_depth_stencil_alpha(struct st_context *st) { struct pipe_depth_stencil_alpha_state *dsa = &st->state.depth_stencil; struct pipe_stencil_ref sr; struct gl_context *ctx = st->ctx; memset(dsa, 0, sizeof(*dsa)); memset(&sr, 0, sizeof(sr)); if (ctx->DrawBuffer->Visual.depthBits > 0) { if (ctx->Depth.Test) { dsa->depth.enabled = 1; dsa->depth.writemask = ctx->Depth.Mask; dsa->depth.func = st_compare_func_to_pipe(ctx->Depth.Func); } if (ctx->Depth.BoundsTest) { dsa->depth.bounds_test = 1; dsa->depth.bounds_min = ctx->Depth.BoundsMin; dsa->depth.bounds_max = ctx->Depth.BoundsMax; } } if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) { dsa->stencil[0].enabled = 1; dsa->stencil[0].func = st_compare_func_to_pipe(ctx->Stencil.Function[0]); dsa->stencil[0].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[0]); dsa->stencil[0].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[0]); dsa->stencil[0].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[0]); dsa->stencil[0].valuemask = ctx->Stencil.ValueMask[0] & 0xff; dsa->stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; sr.ref_value[0] = _mesa_get_stencil_ref(ctx, 0); if (ctx->Stencil._TestTwoSide) { const GLuint back = ctx->Stencil._BackFace; dsa->stencil[1].enabled = 1; dsa->stencil[1].func = st_compare_func_to_pipe(ctx->Stencil.Function[back]); dsa->stencil[1].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[back]); dsa->stencil[1].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[back]); dsa->stencil[1].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[back]); dsa->stencil[1].valuemask = ctx->Stencil.ValueMask[back] & 0xff; dsa->stencil[1].writemask = ctx->Stencil.WriteMask[back] & 0xff; sr.ref_value[1] = _mesa_get_stencil_ref(ctx, back); } else { /* This should be unnecessary. Drivers must not expect this to * contain valid data, except the enabled bit */ dsa->stencil[1] = dsa->stencil[0]; dsa->stencil[1].enabled = 0; sr.ref_value[1] = sr.ref_value[0]; } } if (ctx->Color.AlphaEnabled && !(ctx->DrawBuffer->_IntegerBuffers & 0x1)) { dsa->alpha.enabled = 1; dsa->alpha.func = st_compare_func_to_pipe(ctx->Color.AlphaFunc); dsa->alpha.ref_value = ctx->Color.AlphaRefUnclamped; } cso_set_depth_stencil_alpha(st->cso_context, dsa); cso_set_stencil_ref(st->cso_context, &sr); }