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