Path: blob/21.2-virgl/src/gallium/drivers/svga/svga_pipe_depthstencil.c
4570 views
/**********************************************************1* Copyright 2008-2009 VMware, Inc. All rights reserved.2*3* Permission is hereby granted, free of charge, to any person4* obtaining a copy of this software and associated documentation5* files (the "Software"), to deal in the Software without6* restriction, including without limitation the rights to use, copy,7* modify, merge, publish, distribute, sublicense, and/or sell copies8* of the Software, and to permit persons to whom the Software is9* furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23**********************************************************/2425#include "pipe/p_defines.h"26#include "util/u_bitmask.h"27#include "util/u_inlines.h"28#include "util/u_math.h"29#include "util/u_memory.h"3031#include "svga_context.h"32#include "svga_hw_reg.h"33#include "svga_cmd.h"343536static inline unsigned37svga_translate_compare_func(unsigned func)38{39switch (func) {40case PIPE_FUNC_NEVER: return SVGA3D_CMP_NEVER;41case PIPE_FUNC_LESS: return SVGA3D_CMP_LESS;42case PIPE_FUNC_LEQUAL: return SVGA3D_CMP_LESSEQUAL;43case PIPE_FUNC_GREATER: return SVGA3D_CMP_GREATER;44case PIPE_FUNC_GEQUAL: return SVGA3D_CMP_GREATEREQUAL;45case PIPE_FUNC_NOTEQUAL: return SVGA3D_CMP_NOTEQUAL;46case PIPE_FUNC_EQUAL: return SVGA3D_CMP_EQUAL;47case PIPE_FUNC_ALWAYS: return SVGA3D_CMP_ALWAYS;48default:49assert(0);50return SVGA3D_CMP_ALWAYS;51}52}5354static inline unsigned55svga_translate_stencil_op(unsigned op)56{57switch (op) {58case PIPE_STENCIL_OP_KEEP: return SVGA3D_STENCILOP_KEEP;59case PIPE_STENCIL_OP_ZERO: return SVGA3D_STENCILOP_ZERO;60case PIPE_STENCIL_OP_REPLACE: return SVGA3D_STENCILOP_REPLACE;61case PIPE_STENCIL_OP_INCR: return SVGA3D_STENCILOP_INCRSAT;62case PIPE_STENCIL_OP_DECR: return SVGA3D_STENCILOP_DECRSAT;63case PIPE_STENCIL_OP_INCR_WRAP: return SVGA3D_STENCILOP_INCR;64case PIPE_STENCIL_OP_DECR_WRAP: return SVGA3D_STENCILOP_DECR;65case PIPE_STENCIL_OP_INVERT: return SVGA3D_STENCILOP_INVERT;66default:67assert(0);68return SVGA3D_STENCILOP_KEEP;69}70}717273/**74* Define a vgpu10 depth/stencil state object for the given75* svga depth/stencil state.76*/77static void78define_depth_stencil_state_object(struct svga_context *svga,79struct svga_depth_stencil_state *ds)80{81assert(svga_have_vgpu10(svga));8283ds->id = util_bitmask_add(svga->ds_object_id_bm);8485/* spot check that these comparision tokens are the same */86STATIC_ASSERT(SVGA3D_COMPARISON_NEVER == SVGA3D_CMP_NEVER);87STATIC_ASSERT(SVGA3D_COMPARISON_LESS == SVGA3D_CMP_LESS);88STATIC_ASSERT(SVGA3D_COMPARISON_NOT_EQUAL == SVGA3D_CMP_NOTEQUAL);8990/* Note: we use the ds->stencil[0].enabled value for both the front91* and back-face enables. If single-side stencil is used, we'll have92* set the back state the same as the front state.93*/94SVGA_RETRY(svga, SVGA3D_vgpu10_DefineDepthStencilState95(svga->swc,96ds->id,97/* depth/Z */98ds->zenable,99ds->zwriteenable,100ds->zfunc,101/* Stencil */102ds->stencil[0].enabled, /*f|b*/103ds->stencil[0].enabled, /*f*/104ds->stencil[0].enabled, /*b*/105ds->stencil_mask,106ds->stencil_writemask,107/* front stencil */108ds->stencil[0].fail,109ds->stencil[0].zfail,110ds->stencil[0].pass,111ds->stencil[0].func,112/* back stencil */113ds->stencil[1].fail,114ds->stencil[1].zfail,115ds->stencil[1].pass,116ds->stencil[1].func));117}118119120static void *121svga_create_depth_stencil_state(struct pipe_context *pipe,122const struct pipe_depth_stencil_alpha_state *templ)123{124struct svga_context *svga = svga_context(pipe);125struct svga_depth_stencil_state *ds = CALLOC_STRUCT(svga_depth_stencil_state);126127if (!ds)128return NULL;129130/* Don't try to figure out CW/CCW correspondence with131* stencil[0]/[1] at this point. Presumably this can change as132* back/front face are modified.133*/134ds->stencil[0].enabled = templ->stencil[0].enabled;135if (ds->stencil[0].enabled) {136ds->stencil[0].func = svga_translate_compare_func(templ->stencil[0].func);137ds->stencil[0].fail = svga_translate_stencil_op(templ->stencil[0].fail_op);138ds->stencil[0].zfail = svga_translate_stencil_op(templ->stencil[0].zfail_op);139ds->stencil[0].pass = svga_translate_stencil_op(templ->stencil[0].zpass_op);140141/* SVGA3D has one ref/mask/writemask triple shared between front &142* back face stencil. We really need two:143*/144ds->stencil_mask = templ->stencil[0].valuemask & 0xff;145ds->stencil_writemask = templ->stencil[0].writemask & 0xff;146}147else {148ds->stencil[0].func = SVGA3D_CMP_ALWAYS;149ds->stencil[0].fail = SVGA3D_STENCILOP_KEEP;150ds->stencil[0].zfail = SVGA3D_STENCILOP_KEEP;151ds->stencil[0].pass = SVGA3D_STENCILOP_KEEP;152}153154ds->stencil[1].enabled = templ->stencil[1].enabled;155if (templ->stencil[1].enabled) {156assert(templ->stencil[0].enabled);157/* two-sided stencil */158ds->stencil[1].func = svga_translate_compare_func(templ->stencil[1].func);159ds->stencil[1].fail = svga_translate_stencil_op(templ->stencil[1].fail_op);160ds->stencil[1].zfail = svga_translate_stencil_op(templ->stencil[1].zfail_op);161ds->stencil[1].pass = svga_translate_stencil_op(templ->stencil[1].zpass_op);162163ds->stencil_mask = templ->stencil[1].valuemask & 0xff;164ds->stencil_writemask = templ->stencil[1].writemask & 0xff;165166if (templ->stencil[1].valuemask != templ->stencil[0].valuemask) {167pipe_debug_message(&svga->debug.callback, CONFORMANCE,168"two-sided stencil mask not supported "169"(front=0x%x, back=0x%x)",170templ->stencil[0].valuemask,171templ->stencil[1].valuemask);172}173if (templ->stencil[1].writemask != templ->stencil[0].writemask) {174pipe_debug_message(&svga->debug.callback, CONFORMANCE,175"two-sided stencil writemask not supported "176"(front=0x%x, back=0x%x)",177templ->stencil[0].writemask,178templ->stencil[1].writemask);179}180}181else {182/* back face state is same as front-face state */183ds->stencil[1].func = ds->stencil[0].func;184ds->stencil[1].fail = ds->stencil[0].fail;185ds->stencil[1].zfail = ds->stencil[0].zfail;186ds->stencil[1].pass = ds->stencil[0].pass;187}188189190ds->zenable = templ->depth_enabled;191if (ds->zenable) {192ds->zfunc = svga_translate_compare_func(templ->depth_func);193ds->zwriteenable = templ->depth_writemask;194}195else {196ds->zfunc = SVGA3D_CMP_ALWAYS;197}198199ds->alphatestenable = templ->alpha_enabled;200if (ds->alphatestenable) {201ds->alphafunc = svga_translate_compare_func(templ->alpha_func);202ds->alpharef = templ->alpha_ref_value;203}204else {205ds->alphafunc = SVGA3D_CMP_ALWAYS;206}207208if (svga_have_vgpu10(svga)) {209define_depth_stencil_state_object(svga, ds);210}211212svga->hud.num_depthstencil_objects++;213214SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,215SVGA_STATS_COUNT_DEPTHSTENCILSTATE);216217return ds;218}219220221static void222svga_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)223{224struct svga_context *svga = svga_context(pipe);225226if (svga_have_vgpu10(svga)) {227/* flush any previously queued drawing before changing state */228svga_hwtnl_flush_retry(svga);229}230231svga->curr.depth = (const struct svga_depth_stencil_state *)depth_stencil;232svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA;233}234235236static void237svga_delete_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)238{239struct svga_context *svga = svga_context(pipe);240struct svga_depth_stencil_state *ds =241(struct svga_depth_stencil_state *) depth_stencil;242243if (svga_have_vgpu10(svga)) {244svga_hwtnl_flush_retry(svga);245246assert(ds->id != SVGA3D_INVALID_ID);247248SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilState(svga->swc,249ds->id));250251if (ds->id == svga->state.hw_draw.depth_stencil_id)252svga->state.hw_draw.depth_stencil_id = SVGA3D_INVALID_ID;253254util_bitmask_clear(svga->ds_object_id_bm, ds->id);255ds->id = SVGA3D_INVALID_ID;256}257258FREE(depth_stencil);259svga->hud.num_depthstencil_objects--;260}261262263static void264svga_set_stencil_ref(struct pipe_context *pipe,265const struct pipe_stencil_ref stencil_ref)266{267struct svga_context *svga = svga_context(pipe);268269if (svga_have_vgpu10(svga)) {270/* flush any previously queued drawing before changing state */271svga_hwtnl_flush_retry(svga);272}273274svga->curr.stencil_ref = stencil_ref;275276svga->dirty |= SVGA_NEW_STENCIL_REF;277}278279280static void281svga_set_sample_mask(struct pipe_context *pipe,282unsigned sample_mask)283{284struct svga_context *svga = svga_context(pipe);285286svga->curr.sample_mask = sample_mask;287288svga->dirty |= SVGA_NEW_BLEND; /* See emit_rss_vgpu10() */289}290291292static void293svga_set_min_samples(struct pipe_context *pipe, unsigned min_samples)294{295/* This specifies the minimum number of times the fragment shader296* must run when doing per-sample shading for a MSAA render target.297* For our SVGA3D device, the FS is automatically run in per-sample298* mode if it uses the sample ID or sample position registers.299*/300}301302303void304svga_init_depth_stencil_functions(struct svga_context *svga)305{306svga->pipe.create_depth_stencil_alpha_state = svga_create_depth_stencil_state;307svga->pipe.bind_depth_stencil_alpha_state = svga_bind_depth_stencil_state;308svga->pipe.delete_depth_stencil_alpha_state = svga_delete_depth_stencil_state;309310svga->pipe.set_stencil_ref = svga_set_stencil_ref;311svga->pipe.set_sample_mask = svga_set_sample_mask;312svga->pipe.set_min_samples = svga_set_min_samples;313}314315316