1bf215546Sopenharmony_ci/**********************************************************
2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person
5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation
6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without
7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy,
8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies
9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is
10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be
13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci **********************************************************/
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "pipe/p_defines.h"
27bf215546Sopenharmony_ci#include "util/u_bitmask.h"
28bf215546Sopenharmony_ci#include "util/u_inlines.h"
29bf215546Sopenharmony_ci#include "util/u_math.h"
30bf215546Sopenharmony_ci#include "util/u_memory.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "svga_context.h"
33bf215546Sopenharmony_ci#include "svga_hw_reg.h"
34bf215546Sopenharmony_ci#include "svga_cmd.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cistatic inline unsigned
38bf215546Sopenharmony_cisvga_translate_compare_func(unsigned func)
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci   switch (func) {
41bf215546Sopenharmony_ci   case PIPE_FUNC_NEVER:     return SVGA3D_CMP_NEVER;
42bf215546Sopenharmony_ci   case PIPE_FUNC_LESS:      return SVGA3D_CMP_LESS;
43bf215546Sopenharmony_ci   case PIPE_FUNC_LEQUAL:    return SVGA3D_CMP_LESSEQUAL;
44bf215546Sopenharmony_ci   case PIPE_FUNC_GREATER:   return SVGA3D_CMP_GREATER;
45bf215546Sopenharmony_ci   case PIPE_FUNC_GEQUAL:    return SVGA3D_CMP_GREATEREQUAL;
46bf215546Sopenharmony_ci   case PIPE_FUNC_NOTEQUAL:  return SVGA3D_CMP_NOTEQUAL;
47bf215546Sopenharmony_ci   case PIPE_FUNC_EQUAL:     return SVGA3D_CMP_EQUAL;
48bf215546Sopenharmony_ci   case PIPE_FUNC_ALWAYS:    return SVGA3D_CMP_ALWAYS;
49bf215546Sopenharmony_ci   default:
50bf215546Sopenharmony_ci      assert(0);
51bf215546Sopenharmony_ci      return SVGA3D_CMP_ALWAYS;
52bf215546Sopenharmony_ci   }
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cistatic inline unsigned
56bf215546Sopenharmony_cisvga_translate_stencil_op(unsigned op)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci   switch (op) {
59bf215546Sopenharmony_ci   case PIPE_STENCIL_OP_KEEP:      return SVGA3D_STENCILOP_KEEP;
60bf215546Sopenharmony_ci   case PIPE_STENCIL_OP_ZERO:      return SVGA3D_STENCILOP_ZERO;
61bf215546Sopenharmony_ci   case PIPE_STENCIL_OP_REPLACE:   return SVGA3D_STENCILOP_REPLACE;
62bf215546Sopenharmony_ci   case PIPE_STENCIL_OP_INCR:      return SVGA3D_STENCILOP_INCRSAT;
63bf215546Sopenharmony_ci   case PIPE_STENCIL_OP_DECR:      return SVGA3D_STENCILOP_DECRSAT;
64bf215546Sopenharmony_ci   case PIPE_STENCIL_OP_INCR_WRAP: return SVGA3D_STENCILOP_INCR;
65bf215546Sopenharmony_ci   case PIPE_STENCIL_OP_DECR_WRAP: return SVGA3D_STENCILOP_DECR;
66bf215546Sopenharmony_ci   case PIPE_STENCIL_OP_INVERT:    return SVGA3D_STENCILOP_INVERT;
67bf215546Sopenharmony_ci   default:
68bf215546Sopenharmony_ci      assert(0);
69bf215546Sopenharmony_ci      return SVGA3D_STENCILOP_KEEP;
70bf215546Sopenharmony_ci   }
71bf215546Sopenharmony_ci}
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci/**
75bf215546Sopenharmony_ci * Define a vgpu10 depth/stencil state object for the given
76bf215546Sopenharmony_ci * svga depth/stencil state.
77bf215546Sopenharmony_ci */
78bf215546Sopenharmony_cistatic void
79bf215546Sopenharmony_cidefine_depth_stencil_state_object(struct svga_context *svga,
80bf215546Sopenharmony_ci                                  struct svga_depth_stencil_state *ds)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci   assert(svga_have_vgpu10(svga));
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   ds->id = util_bitmask_add(svga->ds_object_id_bm);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   /* spot check that these comparision tokens are the same */
87bf215546Sopenharmony_ci   STATIC_ASSERT(SVGA3D_COMPARISON_NEVER == SVGA3D_CMP_NEVER);
88bf215546Sopenharmony_ci   STATIC_ASSERT(SVGA3D_COMPARISON_LESS == SVGA3D_CMP_LESS);
89bf215546Sopenharmony_ci   STATIC_ASSERT(SVGA3D_COMPARISON_NOT_EQUAL == SVGA3D_CMP_NOTEQUAL);
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   /* Note: we use the ds->stencil[0].enabled value for both the front
92bf215546Sopenharmony_ci    * and back-face enables.  If single-side stencil is used, we'll have
93bf215546Sopenharmony_ci    * set the back state the same as the front state.
94bf215546Sopenharmony_ci    */
95bf215546Sopenharmony_ci   SVGA_RETRY(svga, SVGA3D_vgpu10_DefineDepthStencilState
96bf215546Sopenharmony_ci              (svga->swc,
97bf215546Sopenharmony_ci               ds->id,
98bf215546Sopenharmony_ci               /* depth/Z */
99bf215546Sopenharmony_ci               ds->zenable,
100bf215546Sopenharmony_ci               ds->zwriteenable,
101bf215546Sopenharmony_ci               ds->zfunc,
102bf215546Sopenharmony_ci               /* Stencil */
103bf215546Sopenharmony_ci               ds->stencil[0].enabled, /*f|b*/
104bf215546Sopenharmony_ci               ds->stencil[0].enabled, /*f*/
105bf215546Sopenharmony_ci               ds->stencil[0].enabled, /*b*/
106bf215546Sopenharmony_ci               ds->stencil_mask,
107bf215546Sopenharmony_ci               ds->stencil_writemask,
108bf215546Sopenharmony_ci               /* front stencil */
109bf215546Sopenharmony_ci               ds->stencil[0].fail,
110bf215546Sopenharmony_ci               ds->stencil[0].zfail,
111bf215546Sopenharmony_ci               ds->stencil[0].pass,
112bf215546Sopenharmony_ci               ds->stencil[0].func,
113bf215546Sopenharmony_ci               /* back stencil */
114bf215546Sopenharmony_ci               ds->stencil[1].fail,
115bf215546Sopenharmony_ci               ds->stencil[1].zfail,
116bf215546Sopenharmony_ci               ds->stencil[1].pass,
117bf215546Sopenharmony_ci               ds->stencil[1].func));
118bf215546Sopenharmony_ci}
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_cistatic void *
122bf215546Sopenharmony_cisvga_create_depth_stencil_state(struct pipe_context *pipe,
123bf215546Sopenharmony_ci				const struct pipe_depth_stencil_alpha_state *templ)
124bf215546Sopenharmony_ci{
125bf215546Sopenharmony_ci   struct svga_context *svga = svga_context(pipe);
126bf215546Sopenharmony_ci   struct svga_depth_stencil_state *ds = CALLOC_STRUCT(svga_depth_stencil_state);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   if (!ds)
129bf215546Sopenharmony_ci      return NULL;
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   /* Don't try to figure out CW/CCW correspondence with
132bf215546Sopenharmony_ci    * stencil[0]/[1] at this point.  Presumably this can change as
133bf215546Sopenharmony_ci    * back/front face are modified.
134bf215546Sopenharmony_ci    */
135bf215546Sopenharmony_ci   ds->stencil[0].enabled = templ->stencil[0].enabled;
136bf215546Sopenharmony_ci   if (ds->stencil[0].enabled) {
137bf215546Sopenharmony_ci      ds->stencil[0].func  = svga_translate_compare_func(templ->stencil[0].func);
138bf215546Sopenharmony_ci      ds->stencil[0].fail  = svga_translate_stencil_op(templ->stencil[0].fail_op);
139bf215546Sopenharmony_ci      ds->stencil[0].zfail = svga_translate_stencil_op(templ->stencil[0].zfail_op);
140bf215546Sopenharmony_ci      ds->stencil[0].pass  = svga_translate_stencil_op(templ->stencil[0].zpass_op);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci      /* SVGA3D has one ref/mask/writemask triple shared between front &
143bf215546Sopenharmony_ci       * back face stencil.  We really need two:
144bf215546Sopenharmony_ci       */
145bf215546Sopenharmony_ci      ds->stencil_mask      = templ->stencil[0].valuemask & 0xff;
146bf215546Sopenharmony_ci      ds->stencil_writemask = templ->stencil[0].writemask & 0xff;
147bf215546Sopenharmony_ci   }
148bf215546Sopenharmony_ci   else {
149bf215546Sopenharmony_ci      ds->stencil[0].func = SVGA3D_CMP_ALWAYS;
150bf215546Sopenharmony_ci      ds->stencil[0].fail = SVGA3D_STENCILOP_KEEP;
151bf215546Sopenharmony_ci      ds->stencil[0].zfail = SVGA3D_STENCILOP_KEEP;
152bf215546Sopenharmony_ci      ds->stencil[0].pass = SVGA3D_STENCILOP_KEEP;
153bf215546Sopenharmony_ci   }
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   ds->stencil[1].enabled = templ->stencil[1].enabled;
156bf215546Sopenharmony_ci   if (templ->stencil[1].enabled) {
157bf215546Sopenharmony_ci      assert(templ->stencil[0].enabled);
158bf215546Sopenharmony_ci      /* two-sided stencil */
159bf215546Sopenharmony_ci      ds->stencil[1].func   = svga_translate_compare_func(templ->stencil[1].func);
160bf215546Sopenharmony_ci      ds->stencil[1].fail   = svga_translate_stencil_op(templ->stencil[1].fail_op);
161bf215546Sopenharmony_ci      ds->stencil[1].zfail  = svga_translate_stencil_op(templ->stencil[1].zfail_op);
162bf215546Sopenharmony_ci      ds->stencil[1].pass   = svga_translate_stencil_op(templ->stencil[1].zpass_op);
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci      ds->stencil_mask      = templ->stencil[1].valuemask & 0xff;
165bf215546Sopenharmony_ci      ds->stencil_writemask = templ->stencil[1].writemask & 0xff;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci      if (templ->stencil[1].valuemask != templ->stencil[0].valuemask) {
168bf215546Sopenharmony_ci         util_debug_message(&svga->debug.callback, CONFORMANCE,
169bf215546Sopenharmony_ci                            "two-sided stencil mask not supported "
170bf215546Sopenharmony_ci                            "(front=0x%x, back=0x%x)",
171bf215546Sopenharmony_ci                            templ->stencil[0].valuemask,
172bf215546Sopenharmony_ci                            templ->stencil[1].valuemask);
173bf215546Sopenharmony_ci      }
174bf215546Sopenharmony_ci      if (templ->stencil[1].writemask != templ->stencil[0].writemask) {
175bf215546Sopenharmony_ci         util_debug_message(&svga->debug.callback, CONFORMANCE,
176bf215546Sopenharmony_ci                            "two-sided stencil writemask not supported "
177bf215546Sopenharmony_ci                            "(front=0x%x, back=0x%x)",
178bf215546Sopenharmony_ci                            templ->stencil[0].writemask,
179bf215546Sopenharmony_ci                            templ->stencil[1].writemask);
180bf215546Sopenharmony_ci      }
181bf215546Sopenharmony_ci   }
182bf215546Sopenharmony_ci   else {
183bf215546Sopenharmony_ci      /* back face state is same as front-face state */
184bf215546Sopenharmony_ci      ds->stencil[1].func = ds->stencil[0].func;
185bf215546Sopenharmony_ci      ds->stencil[1].fail = ds->stencil[0].fail;
186bf215546Sopenharmony_ci      ds->stencil[1].zfail = ds->stencil[0].zfail;
187bf215546Sopenharmony_ci      ds->stencil[1].pass = ds->stencil[0].pass;
188bf215546Sopenharmony_ci   }
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci   ds->zenable = templ->depth_enabled;
192bf215546Sopenharmony_ci   if (ds->zenable) {
193bf215546Sopenharmony_ci      ds->zfunc = svga_translate_compare_func(templ->depth_func);
194bf215546Sopenharmony_ci      ds->zwriteenable = templ->depth_writemask;
195bf215546Sopenharmony_ci   }
196bf215546Sopenharmony_ci   else {
197bf215546Sopenharmony_ci      ds->zfunc = SVGA3D_CMP_ALWAYS;
198bf215546Sopenharmony_ci   }
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   ds->alphatestenable = templ->alpha_enabled;
201bf215546Sopenharmony_ci   if (ds->alphatestenable) {
202bf215546Sopenharmony_ci      ds->alphafunc = svga_translate_compare_func(templ->alpha_func);
203bf215546Sopenharmony_ci      ds->alpharef = templ->alpha_ref_value;
204bf215546Sopenharmony_ci   }
205bf215546Sopenharmony_ci   else {
206bf215546Sopenharmony_ci      ds->alphafunc = SVGA3D_CMP_ALWAYS;
207bf215546Sopenharmony_ci   }
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   if (svga_have_vgpu10(svga)) {
210bf215546Sopenharmony_ci      define_depth_stencil_state_object(svga, ds);
211bf215546Sopenharmony_ci   }
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   svga->hud.num_depthstencil_objects++;
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
216bf215546Sopenharmony_ci                        SVGA_STATS_COUNT_DEPTHSTENCILSTATE);
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   return ds;
219bf215546Sopenharmony_ci}
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_cistatic void
223bf215546Sopenharmony_cisvga_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)
224bf215546Sopenharmony_ci{
225bf215546Sopenharmony_ci   struct svga_context *svga = svga_context(pipe);
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   if (svga_have_vgpu10(svga)) {
228bf215546Sopenharmony_ci      /* flush any previously queued drawing before changing state */
229bf215546Sopenharmony_ci      svga_hwtnl_flush_retry(svga);
230bf215546Sopenharmony_ci   }
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   svga->curr.depth = (const struct svga_depth_stencil_state *)depth_stencil;
233bf215546Sopenharmony_ci   svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA;
234bf215546Sopenharmony_ci}
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_cistatic void
238bf215546Sopenharmony_cisvga_delete_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)
239bf215546Sopenharmony_ci{
240bf215546Sopenharmony_ci   struct svga_context *svga = svga_context(pipe);
241bf215546Sopenharmony_ci   struct svga_depth_stencil_state *ds =
242bf215546Sopenharmony_ci      (struct svga_depth_stencil_state *) depth_stencil;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   if (svga_have_vgpu10(svga)) {
245bf215546Sopenharmony_ci      svga_hwtnl_flush_retry(svga);
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci      assert(ds->id != SVGA3D_INVALID_ID);
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci      SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilState(svga->swc,
250bf215546Sopenharmony_ci                                                              ds->id));
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci      if (ds->id == svga->state.hw_draw.depth_stencil_id)
253bf215546Sopenharmony_ci         svga->state.hw_draw.depth_stencil_id = SVGA3D_INVALID_ID;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci      util_bitmask_clear(svga->ds_object_id_bm, ds->id);
256bf215546Sopenharmony_ci      ds->id = SVGA3D_INVALID_ID;
257bf215546Sopenharmony_ci   }
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   FREE(depth_stencil);
260bf215546Sopenharmony_ci   svga->hud.num_depthstencil_objects--;
261bf215546Sopenharmony_ci}
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_cistatic void
265bf215546Sopenharmony_cisvga_set_stencil_ref(struct pipe_context *pipe,
266bf215546Sopenharmony_ci                     const struct pipe_stencil_ref stencil_ref)
267bf215546Sopenharmony_ci{
268bf215546Sopenharmony_ci   struct svga_context *svga = svga_context(pipe);
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci   if (svga_have_vgpu10(svga)) {
271bf215546Sopenharmony_ci      /* flush any previously queued drawing before changing state */
272bf215546Sopenharmony_ci      svga_hwtnl_flush_retry(svga);
273bf215546Sopenharmony_ci   }
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   svga->curr.stencil_ref = stencil_ref;
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   svga->dirty |= SVGA_NEW_STENCIL_REF;
278bf215546Sopenharmony_ci}
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_cistatic void
282bf215546Sopenharmony_cisvga_set_sample_mask(struct pipe_context *pipe,
283bf215546Sopenharmony_ci                     unsigned sample_mask)
284bf215546Sopenharmony_ci{
285bf215546Sopenharmony_ci   struct svga_context *svga = svga_context(pipe);
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci   svga->curr.sample_mask = sample_mask;
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   svga->dirty |= SVGA_NEW_BLEND; /* See emit_rss_vgpu10() */
290bf215546Sopenharmony_ci}
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_cistatic void
294bf215546Sopenharmony_cisvga_set_min_samples(struct pipe_context *pipe, unsigned min_samples)
295bf215546Sopenharmony_ci{
296bf215546Sopenharmony_ci   /* This specifies the minimum number of times the fragment shader
297bf215546Sopenharmony_ci    * must run when doing per-sample shading for a MSAA render target.
298bf215546Sopenharmony_ci    * For our SVGA3D device, the FS is automatically run in per-sample
299bf215546Sopenharmony_ci    * mode if it uses the sample ID or sample position registers.
300bf215546Sopenharmony_ci    */
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_civoid
305bf215546Sopenharmony_cisvga_init_depth_stencil_functions(struct svga_context *svga)
306bf215546Sopenharmony_ci{
307bf215546Sopenharmony_ci   svga->pipe.create_depth_stencil_alpha_state = svga_create_depth_stencil_state;
308bf215546Sopenharmony_ci   svga->pipe.bind_depth_stencil_alpha_state = svga_bind_depth_stencil_state;
309bf215546Sopenharmony_ci   svga->pipe.delete_depth_stencil_alpha_state = svga_delete_depth_stencil_state;
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci   svga->pipe.set_stencil_ref = svga_set_stencil_ref;
312bf215546Sopenharmony_ci   svga->pipe.set_sample_mask = svga_set_sample_mask;
313bf215546Sopenharmony_ci   svga->pipe.set_min_samples = svga_set_min_samples;
314bf215546Sopenharmony_ci}
315