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