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 26#include "pipe/p_defines.h" 27#include "util/u_bitmask.h" 28#include "util/u_inlines.h" 29#include "util/u_math.h" 30#include "util/u_memory.h" 31 32#include "svga_context.h" 33#include "svga_hw_reg.h" 34#include "svga_cmd.h" 35 36 37static inline unsigned 38svga_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 55static inline unsigned 56svga_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; 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; 66 case PIPE_STENCIL_OP_INVERT: return SVGA3D_STENCILOP_INVERT; 67 default: 68 assert(0); 69 return SVGA3D_STENCILOP_KEEP; 70 } 71} 72 73 74/** 75 * Define a vgpu10 depth/stencil state object for the given 76 * svga depth/stencil state. 77 */ 78static void 79define_depth_stencil_state_object(struct svga_context *svga, 80 struct svga_depth_stencil_state *ds) 81{ 82 assert(svga_have_vgpu10(svga)); 83 84 ds->id = util_bitmask_add(svga->ds_object_id_bm); 85 86 /* spot check that these comparision tokens are the same */ 87 STATIC_ASSERT(SVGA3D_COMPARISON_NEVER == SVGA3D_CMP_NEVER); 88 STATIC_ASSERT(SVGA3D_COMPARISON_LESS == SVGA3D_CMP_LESS); 89 STATIC_ASSERT(SVGA3D_COMPARISON_NOT_EQUAL == SVGA3D_CMP_NOTEQUAL); 90 91 /* Note: we use the ds->stencil[0].enabled value for both the front 92 * and back-face enables. If single-side stencil is used, we'll have 93 * set the back state the same as the front state. 94 */ 95 SVGA_RETRY(svga, SVGA3D_vgpu10_DefineDepthStencilState 96 (svga->swc, 97 ds->id, 98 /* depth/Z */ 99 ds->zenable, 100 ds->zwriteenable, 101 ds->zfunc, 102 /* Stencil */ 103 ds->stencil[0].enabled, /*f|b*/ 104 ds->stencil[0].enabled, /*f*/ 105 ds->stencil[0].enabled, /*b*/ 106 ds->stencil_mask, 107 ds->stencil_writemask, 108 /* front stencil */ 109 ds->stencil[0].fail, 110 ds->stencil[0].zfail, 111 ds->stencil[0].pass, 112 ds->stencil[0].func, 113 /* back stencil */ 114 ds->stencil[1].fail, 115 ds->stencil[1].zfail, 116 ds->stencil[1].pass, 117 ds->stencil[1].func)); 118} 119 120 121static void * 122svga_create_depth_stencil_state(struct pipe_context *pipe, 123 const struct pipe_depth_stencil_alpha_state *templ) 124{ 125 struct svga_context *svga = svga_context(pipe); 126 struct svga_depth_stencil_state *ds = CALLOC_STRUCT(svga_depth_stencil_state); 127 128 if (!ds) 129 return NULL; 130 131 /* Don't try to figure out CW/CCW correspondence with 132 * stencil[0]/[1] at this point. Presumably this can change as 133 * back/front face are modified. 134 */ 135 ds->stencil[0].enabled = templ->stencil[0].enabled; 136 if (ds->stencil[0].enabled) { 137 ds->stencil[0].func = svga_translate_compare_func(templ->stencil[0].func); 138 ds->stencil[0].fail = svga_translate_stencil_op(templ->stencil[0].fail_op); 139 ds->stencil[0].zfail = svga_translate_stencil_op(templ->stencil[0].zfail_op); 140 ds->stencil[0].pass = svga_translate_stencil_op(templ->stencil[0].zpass_op); 141 142 /* SVGA3D has one ref/mask/writemask triple shared between front & 143 * back face stencil. We really need two: 144 */ 145 ds->stencil_mask = templ->stencil[0].valuemask & 0xff; 146 ds->stencil_writemask = templ->stencil[0].writemask & 0xff; 147 } 148 else { 149 ds->stencil[0].func = SVGA3D_CMP_ALWAYS; 150 ds->stencil[0].fail = SVGA3D_STENCILOP_KEEP; 151 ds->stencil[0].zfail = SVGA3D_STENCILOP_KEEP; 152 ds->stencil[0].pass = SVGA3D_STENCILOP_KEEP; 153 } 154 155 ds->stencil[1].enabled = templ->stencil[1].enabled; 156 if (templ->stencil[1].enabled) { 157 assert(templ->stencil[0].enabled); 158 /* two-sided stencil */ 159 ds->stencil[1].func = svga_translate_compare_func(templ->stencil[1].func); 160 ds->stencil[1].fail = svga_translate_stencil_op(templ->stencil[1].fail_op); 161 ds->stencil[1].zfail = svga_translate_stencil_op(templ->stencil[1].zfail_op); 162 ds->stencil[1].pass = svga_translate_stencil_op(templ->stencil[1].zpass_op); 163 164 ds->stencil_mask = templ->stencil[1].valuemask & 0xff; 165 ds->stencil_writemask = templ->stencil[1].writemask & 0xff; 166 167 if (templ->stencil[1].valuemask != templ->stencil[0].valuemask) { 168 util_debug_message(&svga->debug.callback, CONFORMANCE, 169 "two-sided stencil mask not supported " 170 "(front=0x%x, back=0x%x)", 171 templ->stencil[0].valuemask, 172 templ->stencil[1].valuemask); 173 } 174 if (templ->stencil[1].writemask != templ->stencil[0].writemask) { 175 util_debug_message(&svga->debug.callback, CONFORMANCE, 176 "two-sided stencil writemask not supported " 177 "(front=0x%x, back=0x%x)", 178 templ->stencil[0].writemask, 179 templ->stencil[1].writemask); 180 } 181 } 182 else { 183 /* back face state is same as front-face state */ 184 ds->stencil[1].func = ds->stencil[0].func; 185 ds->stencil[1].fail = ds->stencil[0].fail; 186 ds->stencil[1].zfail = ds->stencil[0].zfail; 187 ds->stencil[1].pass = ds->stencil[0].pass; 188 } 189 190 191 ds->zenable = templ->depth_enabled; 192 if (ds->zenable) { 193 ds->zfunc = svga_translate_compare_func(templ->depth_func); 194 ds->zwriteenable = templ->depth_writemask; 195 } 196 else { 197 ds->zfunc = SVGA3D_CMP_ALWAYS; 198 } 199 200 ds->alphatestenable = templ->alpha_enabled; 201 if (ds->alphatestenable) { 202 ds->alphafunc = svga_translate_compare_func(templ->alpha_func); 203 ds->alpharef = templ->alpha_ref_value; 204 } 205 else { 206 ds->alphafunc = SVGA3D_CMP_ALWAYS; 207 } 208 209 if (svga_have_vgpu10(svga)) { 210 define_depth_stencil_state_object(svga, ds); 211 } 212 213 svga->hud.num_depthstencil_objects++; 214 215 SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws, 216 SVGA_STATS_COUNT_DEPTHSTENCILSTATE); 217 218 return ds; 219} 220 221 222static void 223svga_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) 224{ 225 struct svga_context *svga = svga_context(pipe); 226 227 if (svga_have_vgpu10(svga)) { 228 /* flush any previously queued drawing before changing state */ 229 svga_hwtnl_flush_retry(svga); 230 } 231 232 svga->curr.depth = (const struct svga_depth_stencil_state *)depth_stencil; 233 svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA; 234} 235 236 237static void 238svga_delete_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) 239{ 240 struct svga_context *svga = svga_context(pipe); 241 struct svga_depth_stencil_state *ds = 242 (struct svga_depth_stencil_state *) depth_stencil; 243 244 if (svga_have_vgpu10(svga)) { 245 svga_hwtnl_flush_retry(svga); 246 247 assert(ds->id != SVGA3D_INVALID_ID); 248 249 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilState(svga->swc, 250 ds->id)); 251 252 if (ds->id == svga->state.hw_draw.depth_stencil_id) 253 svga->state.hw_draw.depth_stencil_id = SVGA3D_INVALID_ID; 254 255 util_bitmask_clear(svga->ds_object_id_bm, ds->id); 256 ds->id = SVGA3D_INVALID_ID; 257 } 258 259 FREE(depth_stencil); 260 svga->hud.num_depthstencil_objects--; 261} 262 263 264static void 265svga_set_stencil_ref(struct pipe_context *pipe, 266 const struct pipe_stencil_ref stencil_ref) 267{ 268 struct svga_context *svga = svga_context(pipe); 269 270 if (svga_have_vgpu10(svga)) { 271 /* flush any previously queued drawing before changing state */ 272 svga_hwtnl_flush_retry(svga); 273 } 274 275 svga->curr.stencil_ref = stencil_ref; 276 277 svga->dirty |= SVGA_NEW_STENCIL_REF; 278} 279 280 281static void 282svga_set_sample_mask(struct pipe_context *pipe, 283 unsigned sample_mask) 284{ 285 struct svga_context *svga = svga_context(pipe); 286 287 svga->curr.sample_mask = sample_mask; 288 289 svga->dirty |= SVGA_NEW_BLEND; /* See emit_rss_vgpu10() */ 290} 291 292 293static void 294svga_set_min_samples(struct pipe_context *pipe, unsigned min_samples) 295{ 296 /* This specifies the minimum number of times the fragment shader 297 * must run when doing per-sample shading for a MSAA render target. 298 * For our SVGA3D device, the FS is automatically run in per-sample 299 * mode if it uses the sample ID or sample position registers. 300 */ 301} 302 303 304void 305svga_init_depth_stencil_functions(struct svga_context *svga) 306{ 307 svga->pipe.create_depth_stencil_alpha_state = svga_create_depth_stencil_state; 308 svga->pipe.bind_depth_stencil_alpha_state = svga_bind_depth_stencil_state; 309 svga->pipe.delete_depth_stencil_alpha_state = svga_delete_depth_stencil_state; 310 311 svga->pipe.set_stencil_ref = svga_set_stencil_ref; 312 svga->pipe.set_sample_mask = svga_set_sample_mask; 313 svga->pipe.set_min_samples = svga_set_min_samples; 314} 315