lp_bld_depth.c revision 8df65e98998b4c104db30cbba8a38be7eb2a9acd
1343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca/**************************************************************************
2343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca *
3343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * Copyright 2009 VMware, Inc.
4343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * All Rights Reserved.
5343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca *
6343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * Permission is hereby granted, free of charge, to any person obtaining a
7343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * copy of this software and associated documentation files (the
8343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * "Software"), to deal in the Software without restriction, including
9343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * without limitation the rights to use, copy, modify, merge, publish,
10343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * distribute, sub license, and/or sell copies of the Software, and to
11343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * permit persons to whom the Software is furnished to do so, subject to
12343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * the following conditions:
13343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca *
14343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * The above copyright notice and this permission notice (including the
15343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * next paragraph) shall be included in all copies or substantial portions
16343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * of the Software.
17343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca *
18343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca *
26343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca **************************************************************************/
27343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
28343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca/**
295811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * @file
30343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * Depth/stencil testing to LLVM IR translation.
31343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca *
325811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * To be done accurately/efficiently the depth/stencil test must be done with
335811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * the same type/format of the depth/stencil buffer, which implies massaging
345811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * the incoming depths to fit into place. Using a more straightforward
355811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * type/format for depth/stencil values internally and only convert when
365811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * flushing would avoid this, but it would most likely result in depth fighting
375811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * artifacts.
385811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
395811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * We are free to use a different pixel layout though. Since our basic
405811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * processing unit is a quad (2x2 pixel block) we store the depth/stencil
415811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * values tiled, a quad at time. That is, a depth buffer containing
425811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
435811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *  Z11 Z12 Z13 Z14 ...
445811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *  Z21 Z22 Z23 Z24 ...
455811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *  Z31 Z32 Z33 Z34 ...
465811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *  Z41 Z42 Z43 Z44 ...
475811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *  ... ... ... ... ...
485811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
495811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * will actually be stored in memory as
505811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
515811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *  Z11 Z12 Z21 Z22 Z13 Z14 Z23 Z24 ...
525811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *  Z31 Z32 Z41 Z42 Z33 Z34 Z43 Z44 ...
535811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *  ... ... ... ... ... ... ... ... ...
545811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
55ecf85c7d750478e433e640897bb25a18069f14deBrian Paul *
56ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * Stencil test:
57ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * Two-sided stencil test is supported but probably not as efficient as
58ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * it could be.  Currently, we use if/then/else constructs to do the
59ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * operations for front vs. back-facing polygons.  We could probably do
60ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * both the front and back arithmetic then use a Select() instruction to
61ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * choose the result depending on polyon orientation.  We'd have to
62ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * measure performance both ways and see which is better.
635811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
64343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca * @author Jose Fonseca <jfonseca@vmware.com>
65343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca */
66343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
67343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca#include "pipe/p_state.h"
68343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca#include "util/u_format.h"
69343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
70343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca#include "lp_bld_type.h"
71cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul#include "lp_bld_arit.h"
72343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca#include "lp_bld_const.h"
73343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca#include "lp_bld_logic.h"
743d7a88674f9eb3320eeff511968f041426e25023José Fonseca#include "lp_bld_flow.h"
75343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca#include "lp_bld_debug.h"
76343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca#include "lp_bld_depth.h"
77cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul#include "lp_bld_swizzle.h"
78cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
79cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
80ecf85c7d750478e433e640897bb25a18069f14deBrian Paul/** Used to select fields from pipe_stencil_state */
81ecf85c7d750478e433e640897bb25a18069f14deBrian Paulenum stencil_op {
82ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   S_FAIL_OP,
83ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   Z_FAIL_OP,
84ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   Z_PASS_OP
85ecf85c7d750478e433e640897bb25a18069f14deBrian Paul};
86ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
87ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
88cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
89cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul/**
90ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * Do the stencil test comparison (compare FB stencil values against ref value).
91ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * This will be used twice when generating two-sided stencil code.
92ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * \param stencil  the front/back stencil state
93cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul * \param stencilRef  the stencil reference value, replicated as a vector
94ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * \param stencilVals  vector of stencil values from framebuffer
95ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * \return vector mask of pass/fail values (~0 or 0)
96cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul */
97cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paulstatic LLVMValueRef
98ecf85c7d750478e433e640897bb25a18069f14deBrian Paullp_build_stencil_test_single(struct lp_build_context *bld,
99ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                             const struct pipe_stencil_state *stencil,
100ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                             LLVMValueRef stencilRef,
101ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                             LLVMValueRef stencilVals)
102cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul{
103cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   const unsigned stencilMax = 255; /* XXX fix */
104cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   struct lp_type type = bld->type;
105cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   LLVMValueRef res;
106cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
10766b6676d141463b8229e62be6249efd1cb6873a8Brian Paul   assert(type.sign);
10866b6676d141463b8229e62be6249efd1cb6873a8Brian Paul
109cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   assert(stencil->enabled);
110cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
111cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   if (stencil->valuemask != stencilMax) {
112cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      /* compute stencilRef = stencilRef & valuemask */
113cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      LLVMValueRef valuemask = lp_build_const_int_vec(type, stencil->valuemask);
114cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      stencilRef = LLVMBuildAnd(bld->builder, stencilRef, valuemask, "");
115cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      /* compute stencilVals = stencilVals & valuemask */
116cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      stencilVals = LLVMBuildAnd(bld->builder, stencilVals, valuemask, "");
117cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   }
118cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
119fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   res = lp_build_cmp(bld, stencil->func, stencilVals, stencilRef);
120cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
121cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   return res;
122cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul}
123cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
124cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
125cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul/**
126ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * Do the one or two-sided stencil test comparison.
127ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * \sa lp_build_stencil_test_single
128ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * \param face  an integer indicating front (+) or back (-) facing polygon.
129ecf85c7d750478e433e640897bb25a18069f14deBrian Paul *              If NULL, assume front-facing.
130ecf85c7d750478e433e640897bb25a18069f14deBrian Paul */
131ecf85c7d750478e433e640897bb25a18069f14deBrian Paulstatic LLVMValueRef
132ecf85c7d750478e433e640897bb25a18069f14deBrian Paullp_build_stencil_test(struct lp_build_context *bld,
133ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                      const struct pipe_stencil_state stencil[2],
134ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                      LLVMValueRef stencilRefs[2],
135ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                      LLVMValueRef stencilVals,
136ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                      LLVMValueRef face)
137ecf85c7d750478e433e640897bb25a18069f14deBrian Paul{
138ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   LLVMValueRef res;
139ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
140ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   assert(stencil[0].enabled);
141ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
142ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   if (stencil[1].enabled && face) {
143ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      /* do two-sided test */
144ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      struct lp_build_flow_context *flow_ctx;
145ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      struct lp_build_if_state if_ctx;
146ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      LLVMValueRef front_facing;
147ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0);
14822e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul      LLVMValueRef result = bld->undef;
149ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
150ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      flow_ctx = lp_build_flow_create(bld->builder);
151ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_flow_scope_begin(flow_ctx);
152ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
153ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_flow_scope_declare(flow_ctx, &result);
154ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
155ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      /* front_facing = face > 0.0 */
15622e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul      front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, "");
157ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
158ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing);
159ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      {
160ecf85c7d750478e433e640897bb25a18069f14deBrian Paul         result = lp_build_stencil_test_single(bld, &stencil[0],
161ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                               stencilRefs[0], stencilVals);
162ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      }
163ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_else(&if_ctx);
164ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      {
165ecf85c7d750478e433e640897bb25a18069f14deBrian Paul         result = lp_build_stencil_test_single(bld, &stencil[1],
166ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                               stencilRefs[1], stencilVals);
167ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      }
168ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_endif(&if_ctx);
169ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
170ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_flow_scope_end(flow_ctx);
171ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_flow_destroy(flow_ctx);
172ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
173ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      res = result;
174ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   }
175ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   else {
176ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      /* do single-side test */
177ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      res = lp_build_stencil_test_single(bld, &stencil[0],
178ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                         stencilRefs[0], stencilVals);
179ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   }
180ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
181ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   return res;
182ecf85c7d750478e433e640897bb25a18069f14deBrian Paul}
183ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
184ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
185ecf85c7d750478e433e640897bb25a18069f14deBrian Paul/**
186cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul * Apply the stencil operator (add/sub/keep/etc) to the given vector
187cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul * of stencil values.
188cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul * \return  new stencil values vector
189cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul */
190cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paulstatic LLVMValueRef
191ecf85c7d750478e433e640897bb25a18069f14deBrian Paullp_build_stencil_op_single(struct lp_build_context *bld,
192ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                           const struct pipe_stencil_state *stencil,
193ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                           enum stencil_op op,
194ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                           LLVMValueRef stencilRef,
195ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                           LLVMValueRef stencilVals,
196ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                           LLVMValueRef mask)
197cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
198cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul{
199cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   const unsigned stencilMax = 255; /* XXX fix */
200cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   struct lp_type type = bld->type;
201cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   LLVMValueRef res;
202cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   LLVMValueRef max = lp_build_const_int_vec(type, stencilMax);
203ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   unsigned stencil_op;
204ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
20566b6676d141463b8229e62be6249efd1cb6873a8Brian Paul   assert(type.sign);
20666b6676d141463b8229e62be6249efd1cb6873a8Brian Paul
207ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   switch (op) {
208ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   case S_FAIL_OP:
209ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      stencil_op = stencil->fail_op;
210ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      break;
211ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   case Z_FAIL_OP:
212ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      stencil_op = stencil->zfail_op;
213ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      break;
214ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   case Z_PASS_OP:
215ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      stencil_op = stencil->zpass_op;
216ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      break;
217ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   default:
218ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      assert(0 && "Invalid stencil_op mode");
219ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      stencil_op = PIPE_STENCIL_OP_KEEP;
220ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   }
221cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
222cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   switch (stencil_op) {
223cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   case PIPE_STENCIL_OP_KEEP:
224cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = stencilVals;
225fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      /* we can return early for this case */
226fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      return res;
227cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   case PIPE_STENCIL_OP_ZERO:
228cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = bld->zero;
229fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      break;
230cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   case PIPE_STENCIL_OP_REPLACE:
231fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      res = stencilRef;
232fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      break;
233cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   case PIPE_STENCIL_OP_INCR:
234cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = lp_build_add(bld, stencilVals, bld->one);
235cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = lp_build_min(bld, res, max);
236fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      break;
237cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   case PIPE_STENCIL_OP_DECR:
238cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = lp_build_sub(bld, stencilVals, bld->one);
239cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = lp_build_max(bld, res, bld->zero);
240fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      break;
241cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   case PIPE_STENCIL_OP_INCR_WRAP:
242cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = lp_build_add(bld, stencilVals, bld->one);
243cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = LLVMBuildAnd(bld->builder, res, max, "");
244fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      break;
245cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   case PIPE_STENCIL_OP_DECR_WRAP:
246cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = lp_build_sub(bld, stencilVals, bld->one);
247cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = LLVMBuildAnd(bld->builder, res, max, "");
248fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      break;
249cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   case PIPE_STENCIL_OP_INVERT:
250cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = LLVMBuildNot(bld->builder, stencilVals, "");
25166b6676d141463b8229e62be6249efd1cb6873a8Brian Paul      res = LLVMBuildAnd(bld->builder, res, max, "");
252fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      break;
253cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   default:
254cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      assert(0 && "bad stencil op mode");
255cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = NULL;
256cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   }
257cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
258cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   if (stencil->writemask != stencilMax) {
259cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      /* compute res = (res & mask) | (stencilVals & ~mask) */
260cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      LLVMValueRef mask = lp_build_const_int_vec(type, stencil->writemask);
261cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      LLVMValueRef cmask = LLVMBuildNot(bld->builder, mask, "notWritemask");
262cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      LLVMValueRef t1 = LLVMBuildAnd(bld->builder, res, mask, "t1");
263cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      LLVMValueRef t2 = LLVMBuildAnd(bld->builder, stencilVals, cmask, "t2");
264cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul      res = LLVMBuildOr(bld->builder, t1, t2, "t1_or_t2");
265cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   }
266cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
267fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   /* only the update the vector elements enabled by 'mask' */
268fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   res = lp_build_select(bld, mask, res, stencilVals);
269fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
270cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul   return res;
271cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul}
272343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
273343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
2745811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca/**
275ecf85c7d750478e433e640897bb25a18069f14deBrian Paul * Do the one or two-sided stencil test op/update.
276ecf85c7d750478e433e640897bb25a18069f14deBrian Paul */
277ecf85c7d750478e433e640897bb25a18069f14deBrian Paulstatic LLVMValueRef
278ecf85c7d750478e433e640897bb25a18069f14deBrian Paullp_build_stencil_op(struct lp_build_context *bld,
279ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                    const struct pipe_stencil_state stencil[2],
280ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                    enum stencil_op op,
281ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                    LLVMValueRef stencilRefs[2],
282ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                    LLVMValueRef stencilVals,
283ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                    LLVMValueRef mask,
284ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                    LLVMValueRef face)
285ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
286ecf85c7d750478e433e640897bb25a18069f14deBrian Paul{
287ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   assert(stencil[0].enabled);
288ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
289ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   if (stencil[1].enabled && face) {
290ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      /* do two-sided op */
291ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      struct lp_build_flow_context *flow_ctx;
292ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      struct lp_build_if_state if_ctx;
293ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      LLVMValueRef front_facing;
294ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0);
29522e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul      LLVMValueRef result = bld->undef;
296ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
297ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      flow_ctx = lp_build_flow_create(bld->builder);
298ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_flow_scope_begin(flow_ctx);
299ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
300ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_flow_scope_declare(flow_ctx, &result);
301ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
302ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      /* front_facing = face > 0.0 */
30322e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul      front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, "");
304ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
305ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing);
306ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      {
307ecf85c7d750478e433e640897bb25a18069f14deBrian Paul         result = lp_build_stencil_op_single(bld, &stencil[0], op,
308ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                             stencilRefs[0], stencilVals, mask);
309ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      }
310ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_else(&if_ctx);
311ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      {
312ecf85c7d750478e433e640897bb25a18069f14deBrian Paul         result = lp_build_stencil_op_single(bld, &stencil[1], op,
313ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                             stencilRefs[1], stencilVals, mask);
314ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      }
315ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_endif(&if_ctx);
316ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
317ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_flow_scope_end(flow_ctx);
318ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      lp_build_flow_destroy(flow_ctx);
319ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
320ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      return result;
321ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   }
322ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   else {
323ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      /* do single-sided op */
324ecf85c7d750478e433e640897bb25a18069f14deBrian Paul      return lp_build_stencil_op_single(bld, &stencil[0], op,
325ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                        stencilRefs[0], stencilVals, mask);
326ecf85c7d750478e433e640897bb25a18069f14deBrian Paul   }
327ecf85c7d750478e433e640897bb25a18069f14deBrian Paul}
328ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
329ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
330ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
331ecf85c7d750478e433e640897bb25a18069f14deBrian Paul/**
3325811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * Return a type appropriate for depth/stencil testing.
3335811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca */
334b4835ea03d64261da5a892f9590c9977b06920e8José Fonsecastruct lp_type
335343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonsecalp_depth_type(const struct util_format_description *format_desc,
336343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca              unsigned length)
337343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca{
338b4835ea03d64261da5a892f9590c9977b06920e8José Fonseca   struct lp_type type;
339343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   unsigned swizzle;
340343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
341343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
342343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(format_desc->block.width == 1);
343343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(format_desc->block.height == 1);
344343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
345343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   swizzle = format_desc->swizzle[0];
346343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(swizzle < 4);
347343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
348b4835ea03d64261da5a892f9590c9977b06920e8José Fonseca   memset(&type, 0, sizeof type);
349343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   type.width = format_desc->block.bits;
350343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
351343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   if(format_desc->channel[swizzle].type == UTIL_FORMAT_TYPE_FLOAT) {
352343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      type.floating = TRUE;
35352df532b02594e624bddd58ee60fd25075f8ec42José Fonseca      assert(swizzle == 0);
354343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->channel[swizzle].size == format_desc->block.bits);
355343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   }
356343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   else if(format_desc->channel[swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED) {
357343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->block.bits <= 32);
358343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      if(format_desc->channel[swizzle].normalized)
359343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca         type.norm = TRUE;
360343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   }
361343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   else
362343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(0);
363343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
364343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(type.width <= length);
365343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   type.length = length / type.width;
366343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
367343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   return type;
368343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca}
369343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
370343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
3715811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca/**
372cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul * Generate code for performing depth and/or stencil tests.
373cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul * We operate on a vector of values (typically a 2x2 quad).
374cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul *
37522e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul * \param depth  the depth test state
37622e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul * \param stencil  the front/back stencil state
377cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul * \param type  the data type of the fragment depth/stencil values
378cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul * \param format_desc  description of the depth/stencil surface
37922e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul * \param mask  the alive/dead pixel mask for the quad (vector)
38022e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul * \param stencil_refs  the front/back stencil ref values (scalar)
38122e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul * \param z_src  the incoming depth/stencil values (a 2x2 quad)
38222e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul * \param zs_dst_ptr  pointer to depth/stencil values in framebuffer
38322e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul * \param facing  contains float value indicating front/back facing polygon
3845811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca */
385343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonsecavoid
386d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paullp_build_depth_stencil_test(LLVMBuilderRef builder,
387d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul                            const struct pipe_depth_state *depth,
388d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul                            const struct pipe_stencil_state stencil[2],
389d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul                            struct lp_type type,
390d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul                            const struct util_format_description *format_desc,
391d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul                            struct lp_build_mask_context *mask,
392521c61ff017ab15b829abbe9a98b179136a36009Brian Paul                            LLVMValueRef stencil_refs[2],
393d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul                            LLVMValueRef z_src,
39422e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul                            LLVMValueRef zs_dst_ptr,
39522e6dc387039e79f6d1435ae8b7422a6514d5d10Brian Paul                            LLVMValueRef face)
396343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca{
397343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   struct lp_build_context bld;
39866b6676d141463b8229e62be6249efd1cb6873a8Brian Paul   struct lp_build_context sbld;
39966b6676d141463b8229e62be6249efd1cb6873a8Brian Paul   struct lp_type s_type;
400d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul   unsigned z_swizzle, s_swizzle;
401fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   LLVMValueRef zs_dst, z_dst = NULL;
402fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   LLVMValueRef stencil_vals = NULL;
4038df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul   LLVMValueRef z_bitmask = NULL, s_bitmask = NULL, s_shift = NULL;
404fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   LLVMValueRef z_pass = NULL, s_pass_mask = NULL;
405fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   LLVMValueRef orig_mask = mask->value;
406cb1b0b4bec9a1c05bbb762ed04a78dfdf584e3a6Brian Paul
407d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul   assert(depth->enabled || stencil[0].enabled);
408343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
409343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
410343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(format_desc->block.width == 1);
411343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(format_desc->block.height == 1);
412343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
413343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   z_swizzle = format_desc->swizzle[0];
414d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul   s_swizzle = format_desc->swizzle[1];
415d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul
416d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul   assert(z_swizzle != UTIL_FORMAT_SWIZZLE_NONE ||
417d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul          s_swizzle != UTIL_FORMAT_SWIZZLE_NONE);
418343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
4198df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul   if (stencil[0].enabled) {
4208df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul      assert(format_desc->format == PIPE_FORMAT_Z24S8_UNORM ||
4218df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul             format_desc->format == PIPE_FORMAT_S8Z24_UNORM);
4228df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul   }
4238df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul
424343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   /* Sanity checking */
425343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(z_swizzle < 4);
426343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   assert(format_desc->block.bits == type.width);
427343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   if(type.floating) {
428343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(z_swizzle == 0);
429343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_FLOAT);
430343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->channel[z_swizzle].size == format_desc->block.bits);
431343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   }
432343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   else {
433343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED);
434343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->channel[z_swizzle].normalized);
435343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(!type.fixed);
436343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(!type.sign);
437343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(type.norm);
438343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   }
439343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
44066b6676d141463b8229e62be6249efd1cb6873a8Brian Paul   /* Setup build context for Z vals */
441343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   lp_build_context_init(&bld, builder, type);
442343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
44366b6676d141463b8229e62be6249efd1cb6873a8Brian Paul   /* Setup build context for stencil vals */
44466b6676d141463b8229e62be6249efd1cb6873a8Brian Paul   s_type = lp_type_int_vec(type.width);
44566b6676d141463b8229e62be6249efd1cb6873a8Brian Paul   lp_build_context_init(&sbld, builder, s_type);
44666b6676d141463b8229e62be6249efd1cb6873a8Brian Paul
447fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   /* Load current z/stencil value from z/stencil buffer */
448d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul   zs_dst = LLVMBuildLoad(builder, zs_dst_ptr, "");
449343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
450fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   lp_build_name(zs_dst, "zsbufval");
451343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
452343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   /* Align the source depth bits with the destination's, and mask out any
453343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca    * stencil or padding bits from both */
454343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   if(format_desc->channel[z_swizzle].size == format_desc->block.bits) {
455343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(z_swizzle == 0);
456fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      z_dst = zs_dst;
457343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   }
458343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   else {
459d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul      /* shift/mask bits to right-justify the Z bits */
460343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      unsigned padding_left;
461343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      unsigned padding_right;
462343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      unsigned chan;
463343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
464e5a43ac594e7b4c072b90310f7193c341b015f6bJosé Fonseca      assert(format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN);
465343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED);
466343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->channel[z_swizzle].size <= format_desc->block.bits);
467343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      assert(format_desc->channel[z_swizzle].normalized);
468343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
469343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      padding_right = 0;
470343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      for(chan = 0; chan < z_swizzle; ++chan)
471343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca         padding_right += format_desc->channel[chan].size;
472abc160b664c3fbd4c18a2cd3402c9a84f5f2d00fJosé Fonseca      padding_left = format_desc->block.bits -
473abc160b664c3fbd4c18a2cd3402c9a84f5f2d00fJosé Fonseca                     (padding_right + format_desc->channel[z_swizzle].size);
474343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
475343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      if(padding_left || padding_right) {
476d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul         const unsigned long long mask_left = (1ULL << (format_desc->block.bits - padding_left)) - 1;
477d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul         const unsigned long long mask_right = (1ULL << (padding_right)) - 1;
478185be3a87a5b38e8821a560c073975c11dcbd3e9Brian Paul         z_bitmask = lp_build_const_int_vec(type, mask_left ^ mask_right);
479343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      }
480343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
4818df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul      /* If PIPE_FORMAT_Z24S8, we'll shift zs >> 24 to position stencil_vals */
4828df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul      if (format_desc->format == PIPE_FORMAT_Z24S8_UNORM)
4838df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul         s_shift = lp_build_const_int_vec(type, 24);
4848df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul      else
4858df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul         s_shift = lp_build_const_int_vec(type, 0);
4868df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul
4878df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul      s_bitmask = lp_build_const_int_vec(s_type, 0xff);
488fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
4898df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul      stencil_vals = LLVMBuildLShr(builder, zs_dst, s_shift, "");
4908df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul      stencil_vals = LLVMBuildAnd(builder, stencil_vals, s_bitmask, "");
491fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
492343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      if(padding_left)
493d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul         z_src = LLVMBuildLShr(builder, z_src,
494d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul                                lp_build_const_int_vec(type, padding_left), "");
495343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      if(padding_right)
496d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul         z_src = LLVMBuildAnd(builder, z_src, z_bitmask, "");
497343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      if(padding_left || padding_right)
498fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         z_dst = LLVMBuildAnd(builder, zs_dst, z_bitmask, "");
499fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      else
500fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         z_dst = zs_dst;
501343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   }
502343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
503fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   lp_build_name(z_dst, "zsbuf.z");
504fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
505521c61ff017ab15b829abbe9a98b179136a36009Brian Paul   /*
506fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   printf("build depth %d stencil %d\n",
507fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul          depth->enabled,
508fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul          stencil[0].enabled);
509521c61ff017ab15b829abbe9a98b179136a36009Brian Paul   */
510fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
511fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   if (stencil[0].enabled) {
512521c61ff017ab15b829abbe9a98b179136a36009Brian Paul      /* convert scalar stencil refs into vectors */
513521c61ff017ab15b829abbe9a98b179136a36009Brian Paul      stencil_refs[0] = lp_build_broadcast_scalar(&bld, stencil_refs[0]);
514521c61ff017ab15b829abbe9a98b179136a36009Brian Paul      stencil_refs[1] = lp_build_broadcast_scalar(&bld, stencil_refs[1]);
515ecf85c7d750478e433e640897bb25a18069f14deBrian Paul
516343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
51766b6676d141463b8229e62be6249efd1cb6873a8Brian Paul      s_pass_mask = lp_build_stencil_test(&sbld, stencil,
518ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                          stencil_refs, stencil_vals, face);
519343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
520fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      /* apply stencil-fail operator */
521fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      {
522fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         LLVMValueRef s_fail_mask = lp_build_andc(&bld, orig_mask, s_pass_mask);
52366b6676d141463b8229e62be6249efd1cb6873a8Brian Paul         stencil_vals = lp_build_stencil_op(&sbld, stencil, S_FAIL_OP,
524fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul                                            stencil_refs, stencil_vals,
525ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                            s_fail_mask, face);
526fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      }
527fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   }
528fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
529fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   if (depth->enabled) {
530fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      /* compare src Z to dst Z, returning 'pass' mask */
531fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      z_pass = lp_build_cmp(&bld, depth->func, z_src, z_dst);
532fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
533fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      if (!stencil[0].enabled) {
534fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         /* We can potentially skip all remaining operations here, but only
535fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul          * if stencil is disabled because we still need to update the stencil
536fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul          * buffer values.  Don't need to update Z buffer values.
537fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul          */
538fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         lp_build_mask_update(mask, z_pass);
539fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      }
540fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
541fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      if (depth->writemask) {
542fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         if(z_bitmask)
543fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul            z_bitmask = LLVMBuildAnd(builder, mask->value, z_bitmask, "");
544fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         else
545fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul            z_bitmask = mask->value;
546fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
547fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         z_dst = lp_build_select(&bld, z_bitmask, z_src, z_dst);
548fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      }
549fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
550fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      if (stencil[0].enabled) {
551fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         /* update stencil buffer values according to z pass/fail result */
552fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         LLVMValueRef z_fail_mask, z_pass_mask;
553fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
554fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         /* apply Z-fail operator */
555fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         z_fail_mask = lp_build_andc(&bld, orig_mask, z_pass);
55666b6676d141463b8229e62be6249efd1cb6873a8Brian Paul         stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_FAIL_OP,
557fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul                                            stencil_refs, stencil_vals,
558ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                            z_fail_mask, face);
559fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
560fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         /* apply Z-pass operator */
561fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         z_pass_mask = LLVMBuildAnd(bld.builder, orig_mask, z_pass, "");
56266b6676d141463b8229e62be6249efd1cb6873a8Brian Paul         stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_PASS_OP,
563fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul                                            stencil_refs, stencil_vals,
564ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                            z_pass_mask, face);
565fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      }
566fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   }
567fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   else {
568fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      /* No depth test: apply Z-pass operator to stencil buffer values which
569fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul       * passed the stencil test.
570fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul       */
571fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      s_pass_mask = LLVMBuildAnd(bld.builder, orig_mask, s_pass_mask, "");
57266b6676d141463b8229e62be6249efd1cb6873a8Brian Paul      stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_PASS_OP, stencil_refs,
573ecf85c7d750478e433e640897bb25a18069f14deBrian Paul                                         stencil_vals, s_pass_mask, face);
574fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   }
575fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
5768df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul   if (stencil_vals)
5778df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul      stencil_vals = LLVMBuildShl(bld.builder, stencil_vals, s_shift, "");
5788df65e98998b4c104db30cbba8a38be7eb2a9acdBrian Paul
579fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   /* Finally, merge/store the z/stencil values */
580fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   if ((depth->enabled && depth->writemask) ||
581fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul       (stencil[0].enabled && stencil[0].writemask)) {
582fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
583fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      if (z_dst && stencil_vals)
584fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         zs_dst = LLVMBuildOr(bld.builder, z_dst, stencil_vals, "");
585fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      else if (z_dst)
586fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         zs_dst = z_dst;
587343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca      else
588fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul         zs_dst = stencil_vals;
589343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca
590d1c9e598838aeac3c8cb90afee00b2cc683be273Brian Paul      LLVMBuildStore(builder, zs_dst, zs_dst_ptr);
591343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca   }
592fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
593fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   if (s_pass_mask)
594fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      lp_build_mask_update(mask, s_pass_mask);
595fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul
596fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul   if (depth->enabled && stencil[0].enabled)
597fecd4cde501e8b0b5d057a9cc9d2e3af8d853d9eBrian Paul      lp_build_mask_update(mask, z_pass);
598343ccc8dd0d3578aeeb9b635f0933c9f323c7fdaJosé Fonseca}
599