101e04c3fSmrg/****************************************************************************
201e04c3fSmrg * Copyright (C) 2015 Intel Corporation.   All Rights Reserved.
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg ***************************************************************************/
2301e04c3fSmrg
247ec681f3Smrg#include <llvm/Config/llvm-config.h>
257ec681f3Smrg
267ec681f3Smrg#if LLVM_VERSION_MAJOR < 7
2701e04c3fSmrg// llvm redefines DEBUG
2801e04c3fSmrg#pragma push_macro("DEBUG")
2901e04c3fSmrg#undef DEBUG
307ec681f3Smrg#endif
317ec681f3Smrg
327ec681f3Smrg#include <rasterizer/core/state.h>
3301e04c3fSmrg#include "JitManager.h"
347ec681f3Smrg
357ec681f3Smrg#if LLVM_VERSION_MAJOR < 7
3601e04c3fSmrg#pragma pop_macro("DEBUG")
377ec681f3Smrg#endif
3801e04c3fSmrg
3901e04c3fSmrg#include "common/os.h"
4001e04c3fSmrg#include "jit_api.h"
4101e04c3fSmrg#include "gen_state_llvm.h"
4201e04c3fSmrg#include "core/multisample.h"
4301e04c3fSmrg#include "core/state_funcs.h"
4401e04c3fSmrg
4501e04c3fSmrg#include "gallivm/lp_bld_tgsi.h"
467ec681f3Smrg#include "util/format/u_format.h"
4701e04c3fSmrg
4801e04c3fSmrg#include "util/u_memory.h"
4901e04c3fSmrg#include "util/u_inlines.h"
5001e04c3fSmrg#include "util/u_helpers.h"
5101e04c3fSmrg#include "util/u_framebuffer.h"
5201e04c3fSmrg#include "util/u_viewport.h"
5301e04c3fSmrg#include "util/u_prim.h"
5401e04c3fSmrg
5501e04c3fSmrg#include "swr_state.h"
5601e04c3fSmrg#include "swr_context.h"
577ec681f3Smrg#include "gen_surf_state_llvm.h"
5801e04c3fSmrg#include "gen_swr_context_llvm.h"
5901e04c3fSmrg#include "swr_screen.h"
6001e04c3fSmrg#include "swr_resource.h"
6101e04c3fSmrg#include "swr_tex_sample.h"
6201e04c3fSmrg#include "swr_scratch.h"
6301e04c3fSmrg#include "swr_shader.h"
6401e04c3fSmrg#include "swr_fence.h"
6501e04c3fSmrg
6601e04c3fSmrg/* These should be pulled out into separate files as necessary
6701e04c3fSmrg * Just initializing everything here to get going. */
6801e04c3fSmrg
6901e04c3fSmrgstatic void *
7001e04c3fSmrgswr_create_blend_state(struct pipe_context *pipe,
7101e04c3fSmrg                       const struct pipe_blend_state *blend)
7201e04c3fSmrg{
7301e04c3fSmrg   struct swr_blend_state *state = CALLOC_STRUCT(swr_blend_state);
747ec681f3Smrg   assert(state != nullptr);
7501e04c3fSmrg
7601e04c3fSmrg   memcpy(&state->pipe, blend, sizeof(*blend));
7701e04c3fSmrg
7801e04c3fSmrg   struct pipe_blend_state *pipe_blend = &state->pipe;
7901e04c3fSmrg
8001e04c3fSmrg   for (int target = 0;
8101e04c3fSmrg        target < std::min(SWR_NUM_RENDERTARGETS, PIPE_MAX_COLOR_BUFS);
8201e04c3fSmrg        target++) {
8301e04c3fSmrg
8401e04c3fSmrg      struct pipe_rt_blend_state *rt_blend = &pipe_blend->rt[target];
8501e04c3fSmrg      SWR_RENDER_TARGET_BLEND_STATE &blendState =
8601e04c3fSmrg         state->blendState.renderTarget[target];
8701e04c3fSmrg      RENDER_TARGET_BLEND_COMPILE_STATE &compileState =
8801e04c3fSmrg         state->compileState[target];
8901e04c3fSmrg
9001e04c3fSmrg      if (target != 0 && !pipe_blend->independent_blend_enable) {
9101e04c3fSmrg         memcpy(&compileState,
9201e04c3fSmrg                &state->compileState[0],
9301e04c3fSmrg                sizeof(RENDER_TARGET_BLEND_COMPILE_STATE));
9401e04c3fSmrg         continue;
9501e04c3fSmrg      }
9601e04c3fSmrg
9701e04c3fSmrg      compileState.blendEnable = rt_blend->blend_enable;
9801e04c3fSmrg      if (compileState.blendEnable) {
9901e04c3fSmrg         compileState.sourceAlphaBlendFactor =
10001e04c3fSmrg            swr_convert_blend_factor(rt_blend->alpha_src_factor);
10101e04c3fSmrg         compileState.destAlphaBlendFactor =
10201e04c3fSmrg            swr_convert_blend_factor(rt_blend->alpha_dst_factor);
10301e04c3fSmrg         compileState.sourceBlendFactor =
10401e04c3fSmrg            swr_convert_blend_factor(rt_blend->rgb_src_factor);
10501e04c3fSmrg         compileState.destBlendFactor =
10601e04c3fSmrg            swr_convert_blend_factor(rt_blend->rgb_dst_factor);
10701e04c3fSmrg
10801e04c3fSmrg         compileState.colorBlendFunc =
10901e04c3fSmrg            swr_convert_blend_func(rt_blend->rgb_func);
11001e04c3fSmrg         compileState.alphaBlendFunc =
11101e04c3fSmrg            swr_convert_blend_func(rt_blend->alpha_func);
11201e04c3fSmrg      }
11301e04c3fSmrg      compileState.logicOpEnable = state->pipe.logicop_enable;
11401e04c3fSmrg      if (compileState.logicOpEnable) {
11501e04c3fSmrg         compileState.logicOpFunc =
11601e04c3fSmrg            swr_convert_logic_op(state->pipe.logicop_func);
11701e04c3fSmrg      }
11801e04c3fSmrg
11901e04c3fSmrg      blendState.writeDisableRed =
12001e04c3fSmrg         (rt_blend->colormask & PIPE_MASK_R) ? 0 : 1;
12101e04c3fSmrg      blendState.writeDisableGreen =
12201e04c3fSmrg         (rt_blend->colormask & PIPE_MASK_G) ? 0 : 1;
12301e04c3fSmrg      blendState.writeDisableBlue =
12401e04c3fSmrg         (rt_blend->colormask & PIPE_MASK_B) ? 0 : 1;
12501e04c3fSmrg      blendState.writeDisableAlpha =
12601e04c3fSmrg         (rt_blend->colormask & PIPE_MASK_A) ? 0 : 1;
12701e04c3fSmrg
12801e04c3fSmrg      if (rt_blend->colormask == 0)
12901e04c3fSmrg         compileState.blendEnable = false;
13001e04c3fSmrg   }
13101e04c3fSmrg
13201e04c3fSmrg   return state;
13301e04c3fSmrg}
13401e04c3fSmrg
13501e04c3fSmrgstatic void
13601e04c3fSmrgswr_bind_blend_state(struct pipe_context *pipe, void *blend)
13701e04c3fSmrg{
13801e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
13901e04c3fSmrg
14001e04c3fSmrg   if (ctx->blend == blend)
14101e04c3fSmrg      return;
14201e04c3fSmrg
14301e04c3fSmrg   ctx->blend = (swr_blend_state *)blend;
14401e04c3fSmrg
14501e04c3fSmrg   ctx->dirty |= SWR_NEW_BLEND;
14601e04c3fSmrg}
14701e04c3fSmrg
14801e04c3fSmrgstatic void
14901e04c3fSmrgswr_delete_blend_state(struct pipe_context *pipe, void *blend)
15001e04c3fSmrg{
15101e04c3fSmrg   FREE(blend);
15201e04c3fSmrg}
15301e04c3fSmrg
15401e04c3fSmrgstatic void
15501e04c3fSmrgswr_set_blend_color(struct pipe_context *pipe,
15601e04c3fSmrg                    const struct pipe_blend_color *color)
15701e04c3fSmrg{
15801e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
15901e04c3fSmrg
16001e04c3fSmrg   ctx->blend_color = *color;
16101e04c3fSmrg
16201e04c3fSmrg   ctx->dirty |= SWR_NEW_BLEND;
16301e04c3fSmrg}
16401e04c3fSmrg
16501e04c3fSmrgstatic void
16601e04c3fSmrgswr_set_stencil_ref(struct pipe_context *pipe,
1677ec681f3Smrg                    const struct pipe_stencil_ref ref)
16801e04c3fSmrg{
16901e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
17001e04c3fSmrg
1717ec681f3Smrg   ctx->stencil_ref = ref;
17201e04c3fSmrg
17301e04c3fSmrg   ctx->dirty |= SWR_NEW_DEPTH_STENCIL_ALPHA;
17401e04c3fSmrg}
17501e04c3fSmrg
17601e04c3fSmrgstatic void *
17701e04c3fSmrgswr_create_depth_stencil_state(
17801e04c3fSmrg   struct pipe_context *pipe,
17901e04c3fSmrg   const struct pipe_depth_stencil_alpha_state *depth_stencil)
18001e04c3fSmrg{
18101e04c3fSmrg   struct pipe_depth_stencil_alpha_state *state;
18201e04c3fSmrg
18301e04c3fSmrg   state = (pipe_depth_stencil_alpha_state *)mem_dup(depth_stencil,
18401e04c3fSmrg                                                     sizeof *depth_stencil);
18501e04c3fSmrg
18601e04c3fSmrg   return state;
18701e04c3fSmrg}
18801e04c3fSmrg
18901e04c3fSmrgstatic void
19001e04c3fSmrgswr_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)
19101e04c3fSmrg{
19201e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
19301e04c3fSmrg
19401e04c3fSmrg   if (ctx->depth_stencil == (pipe_depth_stencil_alpha_state *)depth_stencil)
19501e04c3fSmrg      return;
19601e04c3fSmrg
19701e04c3fSmrg   ctx->depth_stencil = (pipe_depth_stencil_alpha_state *)depth_stencil;
19801e04c3fSmrg
19901e04c3fSmrg   ctx->dirty |= SWR_NEW_DEPTH_STENCIL_ALPHA;
20001e04c3fSmrg}
20101e04c3fSmrg
20201e04c3fSmrgstatic void
20301e04c3fSmrgswr_delete_depth_stencil_state(struct pipe_context *pipe, void *depth)
20401e04c3fSmrg{
20501e04c3fSmrg   FREE(depth);
20601e04c3fSmrg}
20701e04c3fSmrg
20801e04c3fSmrg
20901e04c3fSmrgstatic void *
21001e04c3fSmrgswr_create_rasterizer_state(struct pipe_context *pipe,
21101e04c3fSmrg                            const struct pipe_rasterizer_state *rast)
21201e04c3fSmrg{
21301e04c3fSmrg   struct pipe_rasterizer_state *state;
21401e04c3fSmrg   state = (pipe_rasterizer_state *)mem_dup(rast, sizeof *rast);
21501e04c3fSmrg
21601e04c3fSmrg   return state;
21701e04c3fSmrg}
21801e04c3fSmrg
21901e04c3fSmrgstatic void
22001e04c3fSmrgswr_bind_rasterizer_state(struct pipe_context *pipe, void *handle)
22101e04c3fSmrg{
22201e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
22301e04c3fSmrg   const struct pipe_rasterizer_state *rasterizer =
22401e04c3fSmrg      (const struct pipe_rasterizer_state *)handle;
22501e04c3fSmrg
22601e04c3fSmrg   if (ctx->rasterizer == (pipe_rasterizer_state *)rasterizer)
22701e04c3fSmrg      return;
22801e04c3fSmrg
22901e04c3fSmrg   ctx->rasterizer = (pipe_rasterizer_state *)rasterizer;
23001e04c3fSmrg
23101e04c3fSmrg   ctx->dirty |= SWR_NEW_RASTERIZER;
23201e04c3fSmrg}
23301e04c3fSmrg
23401e04c3fSmrgstatic void
23501e04c3fSmrgswr_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer)
23601e04c3fSmrg{
23701e04c3fSmrg   FREE(rasterizer);
23801e04c3fSmrg}
23901e04c3fSmrg
24001e04c3fSmrg
24101e04c3fSmrgstatic void *
24201e04c3fSmrgswr_create_sampler_state(struct pipe_context *pipe,
24301e04c3fSmrg                         const struct pipe_sampler_state *sampler)
24401e04c3fSmrg{
24501e04c3fSmrg   struct pipe_sampler_state *state =
24601e04c3fSmrg      (pipe_sampler_state *)mem_dup(sampler, sizeof *sampler);
24701e04c3fSmrg
24801e04c3fSmrg   return state;
24901e04c3fSmrg}
25001e04c3fSmrg
25101e04c3fSmrgstatic void
25201e04c3fSmrgswr_bind_sampler_states(struct pipe_context *pipe,
25301e04c3fSmrg                        enum pipe_shader_type shader,
25401e04c3fSmrg                        unsigned start,
25501e04c3fSmrg                        unsigned num,
25601e04c3fSmrg                        void **samplers)
25701e04c3fSmrg{
25801e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
25901e04c3fSmrg   unsigned i;
26001e04c3fSmrg
26101e04c3fSmrg   assert(shader < PIPE_SHADER_TYPES);
26201e04c3fSmrg   assert(start + num <= ARRAY_SIZE(ctx->samplers[shader]));
26301e04c3fSmrg
26401e04c3fSmrg   /* set the new samplers */
26501e04c3fSmrg   ctx->num_samplers[shader] = num;
26601e04c3fSmrg   for (i = 0; i < num; i++) {
26701e04c3fSmrg      ctx->samplers[shader][start + i] = (pipe_sampler_state *)samplers[i];
26801e04c3fSmrg   }
26901e04c3fSmrg
27001e04c3fSmrg   ctx->dirty |= SWR_NEW_SAMPLER;
27101e04c3fSmrg}
27201e04c3fSmrg
27301e04c3fSmrgstatic void
27401e04c3fSmrgswr_delete_sampler_state(struct pipe_context *pipe, void *sampler)
27501e04c3fSmrg{
27601e04c3fSmrg   FREE(sampler);
27701e04c3fSmrg}
27801e04c3fSmrg
27901e04c3fSmrg
28001e04c3fSmrgstatic struct pipe_sampler_view *
28101e04c3fSmrgswr_create_sampler_view(struct pipe_context *pipe,
28201e04c3fSmrg                        struct pipe_resource *texture,
28301e04c3fSmrg                        const struct pipe_sampler_view *templ)
28401e04c3fSmrg{
28501e04c3fSmrg   struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
28601e04c3fSmrg
28701e04c3fSmrg   if (view) {
28801e04c3fSmrg      *view = *templ;
28901e04c3fSmrg      view->reference.count = 1;
29001e04c3fSmrg      view->texture = NULL;
29101e04c3fSmrg      pipe_resource_reference(&view->texture, texture);
29201e04c3fSmrg      view->context = pipe;
29301e04c3fSmrg   }
29401e04c3fSmrg
29501e04c3fSmrg   return view;
29601e04c3fSmrg}
29701e04c3fSmrg
29801e04c3fSmrgstatic void
29901e04c3fSmrgswr_set_sampler_views(struct pipe_context *pipe,
30001e04c3fSmrg                      enum pipe_shader_type shader,
30101e04c3fSmrg                      unsigned start,
30201e04c3fSmrg                      unsigned num,
3037ec681f3Smrg                      unsigned unbind_num_trailing_slots,
3047ec681f3Smrg                      bool take_ownership,
30501e04c3fSmrg                      struct pipe_sampler_view **views)
30601e04c3fSmrg{
30701e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
30801e04c3fSmrg   uint i;
30901e04c3fSmrg
31001e04c3fSmrg   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
31101e04c3fSmrg
31201e04c3fSmrg   assert(shader < PIPE_SHADER_TYPES);
31301e04c3fSmrg   assert(start + num <= ARRAY_SIZE(ctx->sampler_views[shader]));
31401e04c3fSmrg
31501e04c3fSmrg   /* set the new sampler views */
31601e04c3fSmrg   ctx->num_sampler_views[shader] = num;
31701e04c3fSmrg   for (i = 0; i < num; i++) {
3187ec681f3Smrg      if (take_ownership) {
3197ec681f3Smrg         pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i],
3207ec681f3Smrg                                     NULL);
3217ec681f3Smrg         ctx->sampler_views[shader][start + i] = views[i];
3227ec681f3Smrg      } else {
3237ec681f3Smrg         pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i],
3247ec681f3Smrg                                     views[i]);
3257ec681f3Smrg      }
3267ec681f3Smrg   }
3277ec681f3Smrg   for (; i < num + unbind_num_trailing_slots; i++) {
32801e04c3fSmrg      pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i],
3297ec681f3Smrg                                  NULL);
33001e04c3fSmrg   }
33101e04c3fSmrg
33201e04c3fSmrg   ctx->dirty |= SWR_NEW_SAMPLER_VIEW;
33301e04c3fSmrg}
33401e04c3fSmrg
33501e04c3fSmrgstatic void
33601e04c3fSmrgswr_sampler_view_destroy(struct pipe_context *pipe,
33701e04c3fSmrg                         struct pipe_sampler_view *view)
33801e04c3fSmrg{
33901e04c3fSmrg   pipe_resource_reference(&view->texture, NULL);
34001e04c3fSmrg   FREE(view);
34101e04c3fSmrg}
34201e04c3fSmrg
34301e04c3fSmrgstatic void *
34401e04c3fSmrgswr_create_vs_state(struct pipe_context *pipe,
34501e04c3fSmrg                    const struct pipe_shader_state *vs)
34601e04c3fSmrg{
34701e04c3fSmrg   struct swr_vertex_shader *swr_vs = new swr_vertex_shader;
34801e04c3fSmrg   if (!swr_vs)
34901e04c3fSmrg      return NULL;
35001e04c3fSmrg
35101e04c3fSmrg   swr_vs->pipe.tokens = tgsi_dup_tokens(vs->tokens);
35201e04c3fSmrg   swr_vs->pipe.stream_output = vs->stream_output;
35301e04c3fSmrg
35401e04c3fSmrg   lp_build_tgsi_info(vs->tokens, &swr_vs->info);
35501e04c3fSmrg
35601e04c3fSmrg   swr_vs->soState = {0};
35701e04c3fSmrg
35801e04c3fSmrg   if (swr_vs->pipe.stream_output.num_outputs) {
35901e04c3fSmrg      pipe_stream_output_info *stream_output = &swr_vs->pipe.stream_output;
36001e04c3fSmrg
36101e04c3fSmrg      swr_vs->soState.soEnable = true;
36201e04c3fSmrg      // soState.rasterizerDisable set on state dirty
36301e04c3fSmrg      // soState.streamToRasterizer not used
36401e04c3fSmrg
36501e04c3fSmrg      for (uint32_t i = 0; i < stream_output->num_outputs; i++) {
36601e04c3fSmrg         unsigned attrib_slot = stream_output->output[i].register_index;
36701e04c3fSmrg         attrib_slot = swr_so_adjust_attrib(attrib_slot, swr_vs);
36801e04c3fSmrg         swr_vs->soState.streamMasks[stream_output->output[i].stream] |=
36901e04c3fSmrg            (1 << attrib_slot);
37001e04c3fSmrg      }
37101e04c3fSmrg      for (uint32_t i = 0; i < MAX_SO_STREAMS; i++) {
37201e04c3fSmrg        swr_vs->soState.streamNumEntries[i] =
37301e04c3fSmrg             _mm_popcnt_u32(swr_vs->soState.streamMasks[i]);
37401e04c3fSmrg       }
37501e04c3fSmrg   }
37601e04c3fSmrg
37701e04c3fSmrg   return swr_vs;
37801e04c3fSmrg}
37901e04c3fSmrg
38001e04c3fSmrgstatic void
38101e04c3fSmrgswr_bind_vs_state(struct pipe_context *pipe, void *vs)
38201e04c3fSmrg{
38301e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
38401e04c3fSmrg
38501e04c3fSmrg   if (ctx->vs == vs)
38601e04c3fSmrg      return;
38701e04c3fSmrg
38801e04c3fSmrg   ctx->vs = (swr_vertex_shader *)vs;
38901e04c3fSmrg   ctx->dirty |= SWR_NEW_VS;
39001e04c3fSmrg}
39101e04c3fSmrg
39201e04c3fSmrgstatic void
39301e04c3fSmrgswr_delete_vs_state(struct pipe_context *pipe, void *vs)
39401e04c3fSmrg{
39501e04c3fSmrg   struct swr_vertex_shader *swr_vs = (swr_vertex_shader *)vs;
39601e04c3fSmrg   FREE((void *)swr_vs->pipe.tokens);
39701e04c3fSmrg   struct swr_screen *screen = swr_screen(pipe->screen);
39801e04c3fSmrg
39901e04c3fSmrg   /* Defer deletion of vs state */
40001e04c3fSmrg   swr_fence_work_delete_vs(screen->flush_fence, swr_vs);
40101e04c3fSmrg}
40201e04c3fSmrg
40301e04c3fSmrgstatic void *
40401e04c3fSmrgswr_create_fs_state(struct pipe_context *pipe,
40501e04c3fSmrg                    const struct pipe_shader_state *fs)
40601e04c3fSmrg{
40701e04c3fSmrg   struct swr_fragment_shader *swr_fs = new swr_fragment_shader;
40801e04c3fSmrg   if (!swr_fs)
40901e04c3fSmrg      return NULL;
41001e04c3fSmrg
41101e04c3fSmrg   swr_fs->pipe.tokens = tgsi_dup_tokens(fs->tokens);
41201e04c3fSmrg
41301e04c3fSmrg   lp_build_tgsi_info(fs->tokens, &swr_fs->info);
41401e04c3fSmrg
41501e04c3fSmrg   return swr_fs;
41601e04c3fSmrg}
41701e04c3fSmrg
41801e04c3fSmrg
41901e04c3fSmrgstatic void
42001e04c3fSmrgswr_bind_fs_state(struct pipe_context *pipe, void *fs)
42101e04c3fSmrg{
42201e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
42301e04c3fSmrg
42401e04c3fSmrg   if (ctx->fs == fs)
42501e04c3fSmrg      return;
42601e04c3fSmrg
42701e04c3fSmrg   ctx->fs = (swr_fragment_shader *)fs;
42801e04c3fSmrg   ctx->dirty |= SWR_NEW_FS;
42901e04c3fSmrg}
43001e04c3fSmrg
43101e04c3fSmrgstatic void
43201e04c3fSmrgswr_delete_fs_state(struct pipe_context *pipe, void *fs)
43301e04c3fSmrg{
43401e04c3fSmrg   struct swr_fragment_shader *swr_fs = (swr_fragment_shader *)fs;
43501e04c3fSmrg   FREE((void *)swr_fs->pipe.tokens);
43601e04c3fSmrg   struct swr_screen *screen = swr_screen(pipe->screen);
43701e04c3fSmrg
43801e04c3fSmrg   /* Defer deleton of fs state */
43901e04c3fSmrg   swr_fence_work_delete_fs(screen->flush_fence, swr_fs);
44001e04c3fSmrg}
44101e04c3fSmrg
44201e04c3fSmrgstatic void *
44301e04c3fSmrgswr_create_gs_state(struct pipe_context *pipe,
44401e04c3fSmrg                    const struct pipe_shader_state *gs)
44501e04c3fSmrg{
44601e04c3fSmrg   struct swr_geometry_shader *swr_gs = new swr_geometry_shader;
44701e04c3fSmrg   if (!swr_gs)
44801e04c3fSmrg      return NULL;
44901e04c3fSmrg
45001e04c3fSmrg   swr_gs->pipe.tokens = tgsi_dup_tokens(gs->tokens);
45101e04c3fSmrg   lp_build_tgsi_info(gs->tokens, &swr_gs->info);
45201e04c3fSmrg   return swr_gs;
45301e04c3fSmrg}
45401e04c3fSmrg
45501e04c3fSmrgstatic void
45601e04c3fSmrgswr_bind_gs_state(struct pipe_context *pipe, void *gs)
45701e04c3fSmrg{
45801e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
45901e04c3fSmrg
46001e04c3fSmrg   if (ctx->gs == gs)
46101e04c3fSmrg      return;
46201e04c3fSmrg
46301e04c3fSmrg   ctx->gs = (swr_geometry_shader *)gs;
46401e04c3fSmrg   ctx->dirty |= SWR_NEW_GS;
46501e04c3fSmrg}
46601e04c3fSmrg
46701e04c3fSmrgstatic void
46801e04c3fSmrgswr_delete_gs_state(struct pipe_context *pipe, void *gs)
46901e04c3fSmrg{
47001e04c3fSmrg   struct swr_geometry_shader *swr_gs = (swr_geometry_shader *)gs;
47101e04c3fSmrg   FREE((void *)swr_gs->pipe.tokens);
47201e04c3fSmrg   struct swr_screen *screen = swr_screen(pipe->screen);
47301e04c3fSmrg
47401e04c3fSmrg   /* Defer deleton of fs state */
47501e04c3fSmrg   swr_fence_work_delete_gs(screen->flush_fence, swr_gs);
47601e04c3fSmrg}
47701e04c3fSmrg
4787ec681f3Smrgstatic void *
4797ec681f3Smrgswr_create_tcs_state(struct pipe_context *pipe,
4807ec681f3Smrg                     const struct pipe_shader_state *tcs)
4817ec681f3Smrg{
4827ec681f3Smrg   struct swr_tess_control_shader *swr_tcs = new swr_tess_control_shader;
4837ec681f3Smrg   if (!swr_tcs)
4847ec681f3Smrg      return NULL;
4857ec681f3Smrg
4867ec681f3Smrg   swr_tcs->pipe.tokens = tgsi_dup_tokens(tcs->tokens);
4877ec681f3Smrg   lp_build_tgsi_info(tcs->tokens, &swr_tcs->info);
4887ec681f3Smrg   return swr_tcs;
4897ec681f3Smrg}
4907ec681f3Smrg
4917ec681f3Smrgstatic void
4927ec681f3Smrgswr_bind_tcs_state(struct pipe_context *pipe, void *tcs)
4937ec681f3Smrg{
4947ec681f3Smrg   struct swr_context *ctx = swr_context(pipe);
4957ec681f3Smrg
4967ec681f3Smrg   if (ctx->tcs == tcs)
4977ec681f3Smrg      return;
4987ec681f3Smrg
4997ec681f3Smrg   ctx->tcs = (swr_tess_control_shader *)tcs;
5007ec681f3Smrg   ctx->dirty |= SWR_NEW_TCS;
5017ec681f3Smrg   ctx->dirty |= SWR_NEW_TS;
5027ec681f3Smrg}
5037ec681f3Smrg
5047ec681f3Smrgstatic void
5057ec681f3Smrgswr_delete_tcs_state(struct pipe_context *pipe, void *tcs)
5067ec681f3Smrg{
5077ec681f3Smrg   struct swr_tess_control_shader *swr_tcs = (swr_tess_control_shader *)tcs;
5087ec681f3Smrg   FREE((void *)swr_tcs->pipe.tokens);
5097ec681f3Smrg   struct swr_screen *screen = swr_screen(pipe->screen);
5107ec681f3Smrg
5117ec681f3Smrg   /* Defer deleton of tcs state */
5127ec681f3Smrg   swr_fence_work_delete_tcs(screen->flush_fence, swr_tcs);
5137ec681f3Smrg}
5147ec681f3Smrg
5157ec681f3Smrgstatic void *
5167ec681f3Smrgswr_create_tes_state(struct pipe_context *pipe,
5177ec681f3Smrg                     const struct pipe_shader_state *tes)
5187ec681f3Smrg{
5197ec681f3Smrg   struct swr_tess_evaluation_shader *swr_tes = new swr_tess_evaluation_shader;
5207ec681f3Smrg   if (!swr_tes)
5217ec681f3Smrg      return NULL;
5227ec681f3Smrg
5237ec681f3Smrg   swr_tes->pipe.tokens = tgsi_dup_tokens(tes->tokens);
5247ec681f3Smrg   lp_build_tgsi_info(tes->tokens, &swr_tes->info);
5257ec681f3Smrg   return swr_tes;
5267ec681f3Smrg}
5277ec681f3Smrg
5287ec681f3Smrgstatic void
5297ec681f3Smrgswr_bind_tes_state(struct pipe_context *pipe, void *tes)
5307ec681f3Smrg{
5317ec681f3Smrg   struct swr_context *ctx = swr_context(pipe);
5327ec681f3Smrg
5337ec681f3Smrg   if (ctx->tes == tes)
5347ec681f3Smrg      return;
5357ec681f3Smrg
5367ec681f3Smrg   // Save current tessellator state first
5377ec681f3Smrg   if (ctx->tes != nullptr) {
5387ec681f3Smrg      ctx->tes->ts_state = ctx->tsState;
5397ec681f3Smrg   }
5407ec681f3Smrg
5417ec681f3Smrg   ctx->tes = (swr_tess_evaluation_shader *)tes;
5427ec681f3Smrg
5437ec681f3Smrg   ctx->dirty |= SWR_NEW_TES;
5447ec681f3Smrg   ctx->dirty |= SWR_NEW_TS;
5457ec681f3Smrg}
5467ec681f3Smrg
5477ec681f3Smrgstatic void
5487ec681f3Smrgswr_delete_tes_state(struct pipe_context *pipe, void *tes)
5497ec681f3Smrg{
5507ec681f3Smrg   struct swr_tess_evaluation_shader *swr_tes = (swr_tess_evaluation_shader *)tes;
5517ec681f3Smrg   FREE((void *)swr_tes->pipe.tokens);
5527ec681f3Smrg   struct swr_screen *screen = swr_screen(pipe->screen);
5537ec681f3Smrg
5547ec681f3Smrg   /* Defer deleton of tes state */
5557ec681f3Smrg   swr_fence_work_delete_tes(screen->flush_fence, swr_tes);
5567ec681f3Smrg}
5577ec681f3Smrg
55801e04c3fSmrgstatic void
55901e04c3fSmrgswr_set_constant_buffer(struct pipe_context *pipe,
56001e04c3fSmrg                        enum pipe_shader_type shader,
5617ec681f3Smrg                        uint index, bool take_ownership,
56201e04c3fSmrg                        const struct pipe_constant_buffer *cb)
56301e04c3fSmrg{
56401e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
56501e04c3fSmrg   struct pipe_resource *constants = cb ? cb->buffer : NULL;
56601e04c3fSmrg
56701e04c3fSmrg   assert(shader < PIPE_SHADER_TYPES);
56801e04c3fSmrg   assert(index < ARRAY_SIZE(ctx->constants[shader]));
56901e04c3fSmrg
57001e04c3fSmrg   /* note: reference counting */
5717ec681f3Smrg   util_copy_constant_buffer(&ctx->constants[shader][index], cb, take_ownership);
57201e04c3fSmrg
57301e04c3fSmrg   if (shader == PIPE_SHADER_VERTEX) {
57401e04c3fSmrg      ctx->dirty |= SWR_NEW_VSCONSTANTS;
57501e04c3fSmrg   } else if (shader == PIPE_SHADER_FRAGMENT) {
57601e04c3fSmrg      ctx->dirty |= SWR_NEW_FSCONSTANTS;
57701e04c3fSmrg   } else if (shader == PIPE_SHADER_GEOMETRY) {
57801e04c3fSmrg      ctx->dirty |= SWR_NEW_GSCONSTANTS;
5797ec681f3Smrg   } else if (shader == PIPE_SHADER_TESS_CTRL) {
5807ec681f3Smrg      ctx->dirty |= SWR_NEW_TCSCONSTANTS;
5817ec681f3Smrg   } else if (shader == PIPE_SHADER_TESS_EVAL) {
5827ec681f3Smrg      ctx->dirty |= SWR_NEW_TESCONSTANTS;
58301e04c3fSmrg   }
58401e04c3fSmrg   if (cb && cb->user_buffer) {
58501e04c3fSmrg      pipe_resource_reference(&constants, NULL);
58601e04c3fSmrg   }
58701e04c3fSmrg}
58801e04c3fSmrg
58901e04c3fSmrg
59001e04c3fSmrgstatic void *
59101e04c3fSmrgswr_create_vertex_elements_state(struct pipe_context *pipe,
59201e04c3fSmrg                                 unsigned num_elements,
59301e04c3fSmrg                                 const struct pipe_vertex_element *attribs)
59401e04c3fSmrg{
59501e04c3fSmrg   struct swr_vertex_element_state *velems;
59601e04c3fSmrg   assert(num_elements <= PIPE_MAX_ATTRIBS);
59701e04c3fSmrg   velems = new swr_vertex_element_state;
59801e04c3fSmrg   if (velems) {
5997ec681f3Smrg      memset((void*)&velems->fsState, 0, sizeof(velems->fsState));
60001e04c3fSmrg      velems->fsState.bVertexIDOffsetEnable = true;
60101e04c3fSmrg      velems->fsState.numAttribs = num_elements;
60201e04c3fSmrg      for (unsigned i = 0; i < num_elements; i++) {
60301e04c3fSmrg         // XXX: we should do this keyed on the VS usage info
60401e04c3fSmrg
60501e04c3fSmrg         const struct util_format_description *desc =
6067ec681f3Smrg            util_format_description((enum pipe_format)attribs[i].src_format);
60701e04c3fSmrg
60801e04c3fSmrg         velems->fsState.layout[i].AlignedByteOffset = attribs[i].src_offset;
60901e04c3fSmrg         velems->fsState.layout[i].Format =
6107ec681f3Smrg            mesa_to_swr_format((enum pipe_format)attribs[i].src_format);
61101e04c3fSmrg         velems->fsState.layout[i].StreamIndex =
61201e04c3fSmrg            attribs[i].vertex_buffer_index;
61301e04c3fSmrg         velems->fsState.layout[i].InstanceEnable =
61401e04c3fSmrg            attribs[i].instance_divisor != 0;
61501e04c3fSmrg         velems->fsState.layout[i].ComponentControl0 =
61601e04c3fSmrg            desc->channel[0].type != UTIL_FORMAT_TYPE_VOID
61701e04c3fSmrg            ? ComponentControl::StoreSrc
61801e04c3fSmrg            : ComponentControl::Store0;
61901e04c3fSmrg         velems->fsState.layout[i].ComponentControl1 =
62001e04c3fSmrg            desc->channel[1].type != UTIL_FORMAT_TYPE_VOID
62101e04c3fSmrg            ? ComponentControl::StoreSrc
62201e04c3fSmrg            : ComponentControl::Store0;
62301e04c3fSmrg         velems->fsState.layout[i].ComponentControl2 =
62401e04c3fSmrg            desc->channel[2].type != UTIL_FORMAT_TYPE_VOID
62501e04c3fSmrg            ? ComponentControl::StoreSrc
62601e04c3fSmrg            : ComponentControl::Store0;
62701e04c3fSmrg         velems->fsState.layout[i].ComponentControl3 =
62801e04c3fSmrg            desc->channel[3].type != UTIL_FORMAT_TYPE_VOID
62901e04c3fSmrg            ? ComponentControl::StoreSrc
63001e04c3fSmrg            : ComponentControl::Store1Fp;
63101e04c3fSmrg         velems->fsState.layout[i].ComponentPacking = ComponentEnable::XYZW;
63201e04c3fSmrg         velems->fsState.layout[i].InstanceAdvancementState =
63301e04c3fSmrg            attribs[i].instance_divisor;
63401e04c3fSmrg
63501e04c3fSmrg         /* Calculate the pitch of each stream */
63601e04c3fSmrg         const SWR_FORMAT_INFO &swr_desc = GetFormatInfo(
6377ec681f3Smrg            mesa_to_swr_format((enum pipe_format)attribs[i].src_format));
63801e04c3fSmrg         velems->stream_pitch[attribs[i].vertex_buffer_index] += swr_desc.Bpp;
63901e04c3fSmrg
64001e04c3fSmrg         if (attribs[i].instance_divisor != 0) {
64101e04c3fSmrg            velems->instanced_bufs |= 1U << attribs[i].vertex_buffer_index;
64201e04c3fSmrg            uint32_t *min_instance_div =
64301e04c3fSmrg               &velems->min_instance_div[attribs[i].vertex_buffer_index];
64401e04c3fSmrg            if (!*min_instance_div ||
64501e04c3fSmrg                attribs[i].instance_divisor < *min_instance_div)
64601e04c3fSmrg               *min_instance_div = attribs[i].instance_divisor;
64701e04c3fSmrg         }
64801e04c3fSmrg      }
64901e04c3fSmrg   }
65001e04c3fSmrg
65101e04c3fSmrg   return velems;
65201e04c3fSmrg}
65301e04c3fSmrg
65401e04c3fSmrgstatic void
65501e04c3fSmrgswr_bind_vertex_elements_state(struct pipe_context *pipe, void *velems)
65601e04c3fSmrg{
65701e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
65801e04c3fSmrg   struct swr_vertex_element_state *swr_velems =
65901e04c3fSmrg      (struct swr_vertex_element_state *)velems;
66001e04c3fSmrg
66101e04c3fSmrg   ctx->velems = swr_velems;
66201e04c3fSmrg   ctx->dirty |= SWR_NEW_VERTEX;
66301e04c3fSmrg}
66401e04c3fSmrg
66501e04c3fSmrgstatic void
66601e04c3fSmrgswr_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
66701e04c3fSmrg{
66801e04c3fSmrg   struct swr_vertex_element_state *swr_velems =
66901e04c3fSmrg      (struct swr_vertex_element_state *) velems;
67001e04c3fSmrg   /* XXX Need to destroy fetch shader? */
67101e04c3fSmrg   delete swr_velems;
67201e04c3fSmrg}
67301e04c3fSmrg
67401e04c3fSmrg
67501e04c3fSmrgstatic void
67601e04c3fSmrgswr_set_vertex_buffers(struct pipe_context *pipe,
67701e04c3fSmrg                       unsigned start_slot,
67801e04c3fSmrg                       unsigned num_elements,
6797ec681f3Smrg                       unsigned unbind_num_trailing_slots,
6807ec681f3Smrg                       bool take_ownership,
68101e04c3fSmrg                       const struct pipe_vertex_buffer *buffers)
68201e04c3fSmrg{
68301e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
68401e04c3fSmrg
68501e04c3fSmrg   assert(num_elements <= PIPE_MAX_ATTRIBS);
68601e04c3fSmrg
68701e04c3fSmrg   util_set_vertex_buffers_count(ctx->vertex_buffer,
68801e04c3fSmrg                                 &ctx->num_vertex_buffers,
68901e04c3fSmrg                                 buffers,
69001e04c3fSmrg                                 start_slot,
6917ec681f3Smrg                                 num_elements,
6927ec681f3Smrg                                 unbind_num_trailing_slots,
6937ec681f3Smrg                                 take_ownership);
69401e04c3fSmrg
69501e04c3fSmrg   ctx->dirty |= SWR_NEW_VERTEX;
69601e04c3fSmrg}
69701e04c3fSmrg
69801e04c3fSmrg
69901e04c3fSmrgstatic void
70001e04c3fSmrgswr_set_polygon_stipple(struct pipe_context *pipe,
70101e04c3fSmrg                        const struct pipe_poly_stipple *stipple)
70201e04c3fSmrg{
70301e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
70401e04c3fSmrg
70501e04c3fSmrg   ctx->poly_stipple.pipe = *stipple; /* struct copy */
70601e04c3fSmrg   ctx->dirty |= SWR_NEW_STIPPLE;
70701e04c3fSmrg}
70801e04c3fSmrg
70901e04c3fSmrgstatic void
71001e04c3fSmrgswr_set_clip_state(struct pipe_context *pipe,
71101e04c3fSmrg                   const struct pipe_clip_state *clip)
71201e04c3fSmrg{
71301e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
71401e04c3fSmrg
71501e04c3fSmrg   ctx->clip = *clip;
71601e04c3fSmrg   /* XXX Unimplemented, but prevents crash */
71701e04c3fSmrg
71801e04c3fSmrg   ctx->dirty |= SWR_NEW_CLIP;
71901e04c3fSmrg}
72001e04c3fSmrg
72101e04c3fSmrg
72201e04c3fSmrgstatic void
72301e04c3fSmrgswr_set_scissor_states(struct pipe_context *pipe,
72401e04c3fSmrg                       unsigned start_slot,
7257ec681f3Smrg                       unsigned num_scissors,
7267ec681f3Smrg                       const struct pipe_scissor_state *scissors)
72701e04c3fSmrg{
72801e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
72901e04c3fSmrg
7307ec681f3Smrg   memcpy(ctx->scissors + start_slot, scissors,
7317ec681f3Smrg          sizeof(struct pipe_scissor_state) * num_scissors);
7327ec681f3Smrg
7337ec681f3Smrg   for (unsigned i = 0; i < num_scissors; i++) {
7347ec681f3Smrg      auto idx = start_slot + i;
7357ec681f3Smrg      ctx->swr_scissors[idx].xmin = scissors[idx].minx;
7367ec681f3Smrg      ctx->swr_scissors[idx].xmax = scissors[idx].maxx;
7377ec681f3Smrg      ctx->swr_scissors[idx].ymin = scissors[idx].miny;
7387ec681f3Smrg      ctx->swr_scissors[idx].ymax = scissors[idx].maxy;
7397ec681f3Smrg   }
74001e04c3fSmrg   ctx->dirty |= SWR_NEW_SCISSOR;
74101e04c3fSmrg}
74201e04c3fSmrg
74301e04c3fSmrgstatic void
74401e04c3fSmrgswr_set_viewport_states(struct pipe_context *pipe,
74501e04c3fSmrg                        unsigned start_slot,
74601e04c3fSmrg                        unsigned num_viewports,
74701e04c3fSmrg                        const struct pipe_viewport_state *vpt)
74801e04c3fSmrg{
74901e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
75001e04c3fSmrg
7517ec681f3Smrg   memcpy(ctx->viewports + start_slot, vpt, sizeof(struct pipe_viewport_state) * num_viewports);
75201e04c3fSmrg   ctx->dirty |= SWR_NEW_VIEWPORT;
75301e04c3fSmrg}
75401e04c3fSmrg
75501e04c3fSmrg
75601e04c3fSmrgstatic void
75701e04c3fSmrgswr_set_framebuffer_state(struct pipe_context *pipe,
75801e04c3fSmrg                          const struct pipe_framebuffer_state *fb)
75901e04c3fSmrg{
76001e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
76101e04c3fSmrg
7627ec681f3Smrg   bool changed = !util_framebuffer_state_equal(&ctx->framebuffer, fb);
76301e04c3fSmrg
76401e04c3fSmrg   assert(fb->width <= KNOB_GUARDBAND_WIDTH);
76501e04c3fSmrg   assert(fb->height <= KNOB_GUARDBAND_HEIGHT);
76601e04c3fSmrg
76701e04c3fSmrg   if (changed) {
76801e04c3fSmrg      util_copy_framebuffer_state(&ctx->framebuffer, fb);
76901e04c3fSmrg
77001e04c3fSmrg      /* 0 and 1 both indicate no msaa.  Core doesn't understand 0 samples */
77101e04c3fSmrg      ctx->framebuffer.samples = std::max((ubyte)1, ctx->framebuffer.samples);
77201e04c3fSmrg
77301e04c3fSmrg      ctx->dirty |= SWR_NEW_FRAMEBUFFER;
77401e04c3fSmrg   }
77501e04c3fSmrg}
77601e04c3fSmrg
77701e04c3fSmrg
77801e04c3fSmrgstatic void
77901e04c3fSmrgswr_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
78001e04c3fSmrg{
78101e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
78201e04c3fSmrg
78301e04c3fSmrg   if (sample_mask != ctx->sample_mask) {
78401e04c3fSmrg      ctx->sample_mask = sample_mask;
78501e04c3fSmrg      ctx->dirty |= SWR_NEW_RASTERIZER;
78601e04c3fSmrg   }
78701e04c3fSmrg}
78801e04c3fSmrg
78901e04c3fSmrg/*
79001e04c3fSmrg * MSAA fixed sample position table
79101e04c3fSmrg * used by update_derived and get_sample_position
79201e04c3fSmrg * (integer locations on a 16x16 grid)
79301e04c3fSmrg */
79401e04c3fSmrgstatic const uint8_t swr_sample_positions[][2] =
79501e04c3fSmrg{ /* 1x*/ { 8, 8},
79601e04c3fSmrg  /* 2x*/ {12,12},{ 4, 4},
79701e04c3fSmrg  /* 4x*/ { 6, 2},{14, 6},{ 2,10},{10,14},
79801e04c3fSmrg  /* 8x*/ { 9, 5},{ 7,11},{13, 9},{ 5, 3},
79901e04c3fSmrg          { 3,13},{ 1, 7},{11,15},{15, 1},
80001e04c3fSmrg  /*16x*/ { 9, 9},{ 7, 5},{ 5,10},{12, 7},
80101e04c3fSmrg          { 3, 6},{10,13},{13,11},{11, 3},
80201e04c3fSmrg          { 6,14},{ 8, 1},{ 4, 2},{ 2,12},
80301e04c3fSmrg          { 0, 8},{15, 4},{14,15},{ 1, 0} };
80401e04c3fSmrg
80501e04c3fSmrgstatic void
80601e04c3fSmrgswr_get_sample_position(struct pipe_context *pipe,
80701e04c3fSmrg                        unsigned sample_count, unsigned sample_index,
80801e04c3fSmrg                        float *out_value)
80901e04c3fSmrg{
81001e04c3fSmrg   /* validate sample_count */
81101e04c3fSmrg   sample_count = GetNumSamples(GetSampleCount(sample_count));
81201e04c3fSmrg
81301e04c3fSmrg   const uint8_t *sample = swr_sample_positions[sample_count-1 + sample_index];
81401e04c3fSmrg   out_value[0] = sample[0] / 16.0f;
81501e04c3fSmrg   out_value[1] = sample[1] / 16.0f;
81601e04c3fSmrg}
81701e04c3fSmrg
81801e04c3fSmrg
81901e04c3fSmrg/*
82001e04c3fSmrg * Update resource in-use status
82101e04c3fSmrg * All resources bound to color or depth targets marked as WRITE resources.
82201e04c3fSmrg * VBO Vertex/index buffers and texture views marked as READ resources.
82301e04c3fSmrg */
82401e04c3fSmrgvoid
82501e04c3fSmrgswr_update_resource_status(struct pipe_context *pipe,
82601e04c3fSmrg                           const struct pipe_draw_info *p_draw_info)
82701e04c3fSmrg{
82801e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
82901e04c3fSmrg   struct pipe_framebuffer_state *fb = &ctx->framebuffer;
83001e04c3fSmrg
83101e04c3fSmrg   /* colorbuffer targets */
83201e04c3fSmrg   if (fb->nr_cbufs)
83301e04c3fSmrg      for (uint32_t i = 0; i < fb->nr_cbufs; ++i)
83401e04c3fSmrg         if (fb->cbufs[i])
83501e04c3fSmrg            swr_resource_write(fb->cbufs[i]->texture);
83601e04c3fSmrg
83701e04c3fSmrg   /* depth/stencil target */
83801e04c3fSmrg   if (fb->zsbuf)
83901e04c3fSmrg      swr_resource_write(fb->zsbuf->texture);
84001e04c3fSmrg
84101e04c3fSmrg   /* VBO vertex buffers */
84201e04c3fSmrg   for (uint32_t i = 0; i < ctx->num_vertex_buffers; i++) {
84301e04c3fSmrg      struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i];
8449f464c52Smaya      if (!vb->is_user_buffer && vb->buffer.resource)
84501e04c3fSmrg         swr_resource_read(vb->buffer.resource);
84601e04c3fSmrg   }
84701e04c3fSmrg
84801e04c3fSmrg   /* VBO index buffer */
84901e04c3fSmrg   if (p_draw_info && p_draw_info->index_size) {
85001e04c3fSmrg      if (!p_draw_info->has_user_indices)
85101e04c3fSmrg         swr_resource_read(p_draw_info->index.resource);
85201e04c3fSmrg   }
85301e04c3fSmrg
85401e04c3fSmrg   /* transform feedback buffers */
85501e04c3fSmrg   for (uint32_t i = 0; i < ctx->num_so_targets; i++) {
85601e04c3fSmrg      struct pipe_stream_output_target *target = ctx->so_targets[i];
85701e04c3fSmrg      if (target && target->buffer)
85801e04c3fSmrg         swr_resource_write(target->buffer);
85901e04c3fSmrg   }
86001e04c3fSmrg
86101e04c3fSmrg   /* texture sampler views */
86201e04c3fSmrg   for (uint32_t j : {PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT}) {
86301e04c3fSmrg      for (uint32_t i = 0; i < ctx->num_sampler_views[j]; i++) {
86401e04c3fSmrg         struct pipe_sampler_view *view = ctx->sampler_views[j][i];
86501e04c3fSmrg         if (view)
86601e04c3fSmrg            swr_resource_read(view->texture);
86701e04c3fSmrg      }
86801e04c3fSmrg   }
86901e04c3fSmrg
87001e04c3fSmrg   /* constant buffers */
87101e04c3fSmrg   for (uint32_t j : {PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT}) {
87201e04c3fSmrg      for (uint32_t i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
87301e04c3fSmrg         struct pipe_constant_buffer *cb = &ctx->constants[j][i];
87401e04c3fSmrg         if (cb->buffer)
87501e04c3fSmrg            swr_resource_read(cb->buffer);
87601e04c3fSmrg      }
87701e04c3fSmrg   }
87801e04c3fSmrg}
87901e04c3fSmrg
88001e04c3fSmrgstatic void
88101e04c3fSmrgswr_update_texture_state(struct swr_context *ctx,
88201e04c3fSmrg                         enum pipe_shader_type shader_type,
88301e04c3fSmrg                         unsigned num_sampler_views,
88401e04c3fSmrg                         swr_jit_texture *textures)
88501e04c3fSmrg{
88601e04c3fSmrg   for (unsigned i = 0; i < num_sampler_views; i++) {
88701e04c3fSmrg      struct pipe_sampler_view *view =
88801e04c3fSmrg         ctx->sampler_views[shader_type][i];
88901e04c3fSmrg      struct swr_jit_texture *jit_tex = &textures[i];
89001e04c3fSmrg
89101e04c3fSmrg      memset(jit_tex, 0, sizeof(*jit_tex));
89201e04c3fSmrg      if (view) {
89301e04c3fSmrg         struct pipe_resource *res = view->texture;
89401e04c3fSmrg         struct swr_resource *swr_res = swr_resource(res);
89501e04c3fSmrg         SWR_SURFACE_STATE *swr = &swr_res->swr;
89601e04c3fSmrg         size_t *mip_offsets = swr_res->mip_offsets;
89701e04c3fSmrg         if (swr_res->has_depth && swr_res->has_stencil &&
89801e04c3fSmrg            !util_format_has_depth(util_format_description(view->format))) {
89901e04c3fSmrg            swr = &swr_res->secondary;
90001e04c3fSmrg            mip_offsets = swr_res->secondary_mip_offsets;
90101e04c3fSmrg         }
90201e04c3fSmrg
90301e04c3fSmrg         jit_tex->width = res->width0;
90401e04c3fSmrg         jit_tex->height = res->height0;
90501e04c3fSmrg         jit_tex->base_ptr = (uint8_t*)swr->xpBaseAddress;
9067ec681f3Smrg         jit_tex->num_samples = swr->numSamples;
9077ec681f3Smrg         jit_tex->sample_stride = 0;
90801e04c3fSmrg         if (view->target != PIPE_BUFFER) {
90901e04c3fSmrg            jit_tex->first_level = view->u.tex.first_level;
91001e04c3fSmrg            jit_tex->last_level = view->u.tex.last_level;
91101e04c3fSmrg            if (view->target == PIPE_TEXTURE_3D)
91201e04c3fSmrg               jit_tex->depth = res->depth0;
91301e04c3fSmrg            else
91401e04c3fSmrg               jit_tex->depth =
91501e04c3fSmrg                  view->u.tex.last_layer - view->u.tex.first_layer + 1;
91601e04c3fSmrg            jit_tex->base_ptr += view->u.tex.first_layer *
91701e04c3fSmrg               swr->qpitch * swr->pitch;
91801e04c3fSmrg         } else {
91901e04c3fSmrg            unsigned view_blocksize = util_format_get_blocksize(view->format);
92001e04c3fSmrg            jit_tex->base_ptr += view->u.buf.offset;
92101e04c3fSmrg            jit_tex->width = view->u.buf.size / view_blocksize;
92201e04c3fSmrg            jit_tex->depth = 1;
92301e04c3fSmrg         }
92401e04c3fSmrg
92501e04c3fSmrg         for (unsigned level = jit_tex->first_level;
92601e04c3fSmrg              level <= jit_tex->last_level;
92701e04c3fSmrg              level++) {
92801e04c3fSmrg            jit_tex->row_stride[level] = swr->pitch;
92901e04c3fSmrg            jit_tex->img_stride[level] = swr->qpitch * swr->pitch;
93001e04c3fSmrg            jit_tex->mip_offsets[level] = mip_offsets[level];
93101e04c3fSmrg         }
93201e04c3fSmrg      }
93301e04c3fSmrg   }
93401e04c3fSmrg}
93501e04c3fSmrg
93601e04c3fSmrgstatic void
93701e04c3fSmrgswr_update_sampler_state(struct swr_context *ctx,
93801e04c3fSmrg                         enum pipe_shader_type shader_type,
93901e04c3fSmrg                         unsigned num_samplers,
94001e04c3fSmrg                         swr_jit_sampler *samplers)
94101e04c3fSmrg{
94201e04c3fSmrg   for (unsigned i = 0; i < num_samplers; i++) {
94301e04c3fSmrg      const struct pipe_sampler_state *sampler =
94401e04c3fSmrg         ctx->samplers[shader_type][i];
94501e04c3fSmrg
94601e04c3fSmrg      if (sampler) {
94701e04c3fSmrg         samplers[i].min_lod = sampler->min_lod;
94801e04c3fSmrg         samplers[i].max_lod = sampler->max_lod;
94901e04c3fSmrg         samplers[i].lod_bias = sampler->lod_bias;
95001e04c3fSmrg         COPY_4V(samplers[i].border_color, sampler->border_color.f);
95101e04c3fSmrg      }
95201e04c3fSmrg   }
95301e04c3fSmrg}
95401e04c3fSmrg
95501e04c3fSmrgstatic void
95601e04c3fSmrgswr_update_constants(struct swr_context *ctx, enum pipe_shader_type shaderType)
95701e04c3fSmrg{
95801e04c3fSmrg   swr_draw_context *pDC = &ctx->swrDC;
95901e04c3fSmrg
96001e04c3fSmrg   const float **constant;
96101e04c3fSmrg   uint32_t *num_constants;
96201e04c3fSmrg   struct swr_scratch_space *scratch;
96301e04c3fSmrg
96401e04c3fSmrg   switch (shaderType) {
96501e04c3fSmrg   case PIPE_SHADER_VERTEX:
96601e04c3fSmrg      constant = pDC->constantVS;
96701e04c3fSmrg      num_constants = pDC->num_constantsVS;
96801e04c3fSmrg      scratch = &ctx->scratch->vs_constants;
96901e04c3fSmrg      break;
97001e04c3fSmrg   case PIPE_SHADER_FRAGMENT:
97101e04c3fSmrg      constant = pDC->constantFS;
97201e04c3fSmrg      num_constants = pDC->num_constantsFS;
97301e04c3fSmrg      scratch = &ctx->scratch->fs_constants;
97401e04c3fSmrg      break;
97501e04c3fSmrg   case PIPE_SHADER_GEOMETRY:
97601e04c3fSmrg      constant = pDC->constantGS;
97701e04c3fSmrg      num_constants = pDC->num_constantsGS;
97801e04c3fSmrg      scratch = &ctx->scratch->gs_constants;
97901e04c3fSmrg      break;
9807ec681f3Smrg   case PIPE_SHADER_TESS_CTRL:
9817ec681f3Smrg      constant = pDC->constantTCS;
9827ec681f3Smrg      num_constants = pDC->num_constantsTCS;
9837ec681f3Smrg      scratch = &ctx->scratch->tcs_constants;
9847ec681f3Smrg      break;
9857ec681f3Smrg   case PIPE_SHADER_TESS_EVAL:
9867ec681f3Smrg      constant = pDC->constantTES;
9877ec681f3Smrg      num_constants = pDC->num_constantsTES;
9887ec681f3Smrg      scratch = &ctx->scratch->tes_constants;
9897ec681f3Smrg      break;
99001e04c3fSmrg   default:
9917ec681f3Smrg      assert(0 && "Unsupported shader type constants");
99201e04c3fSmrg      return;
99301e04c3fSmrg   }
99401e04c3fSmrg
99501e04c3fSmrg   for (UINT i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
99601e04c3fSmrg      const pipe_constant_buffer *cb = &ctx->constants[shaderType][i];
99701e04c3fSmrg      num_constants[i] = cb->buffer_size;
99801e04c3fSmrg      if (cb->buffer) {
99901e04c3fSmrg         constant[i] =
100001e04c3fSmrg            (const float *)(swr_resource_data(cb->buffer) +
100101e04c3fSmrg                            cb->buffer_offset);
100201e04c3fSmrg      } else {
100301e04c3fSmrg         /* Need to copy these constants to scratch space */
100401e04c3fSmrg         if (cb->user_buffer && cb->buffer_size) {
100501e04c3fSmrg            const void *ptr =
100601e04c3fSmrg               ((const uint8_t *)cb->user_buffer + cb->buffer_offset);
100701e04c3fSmrg            uint32_t size = AlignUp(cb->buffer_size, 4);
100801e04c3fSmrg            ptr = swr_copy_to_scratch_space(ctx, scratch, ptr, size);
100901e04c3fSmrg            constant[i] = (const float *)ptr;
101001e04c3fSmrg         }
101101e04c3fSmrg      }
101201e04c3fSmrg   }
101301e04c3fSmrg}
101401e04c3fSmrg
101501e04c3fSmrgstatic bool
101601e04c3fSmrgswr_change_rt(struct swr_context *ctx,
101701e04c3fSmrg              unsigned attachment,
101801e04c3fSmrg              const struct pipe_surface *sf)
101901e04c3fSmrg{
102001e04c3fSmrg   swr_draw_context *pDC = &ctx->swrDC;
102101e04c3fSmrg   struct SWR_SURFACE_STATE *rt = &pDC->renderTargets[attachment];
102201e04c3fSmrg
102301e04c3fSmrg   /* Do nothing if the render target hasn't changed */
102401e04c3fSmrg   if ((!sf || !sf->texture) && (void*)(rt->xpBaseAddress) == nullptr)
102501e04c3fSmrg      return false;
102601e04c3fSmrg
102701e04c3fSmrg   /* Deal with disabling RT up front */
102801e04c3fSmrg   if (!sf || !sf->texture) {
102901e04c3fSmrg      /* If detaching attachment, mark tiles as RESOLVED so core
103001e04c3fSmrg       * won't try to load from non-existent target. */
103101e04c3fSmrg      swr_store_render_target(&ctx->pipe, attachment, SWR_TILE_RESOLVED);
103201e04c3fSmrg      *rt = {0};
103301e04c3fSmrg      return true;
103401e04c3fSmrg   }
103501e04c3fSmrg
103601e04c3fSmrg   const struct swr_resource *swr = swr_resource(sf->texture);
103701e04c3fSmrg   const SWR_SURFACE_STATE *swr_surface = &swr->swr;
103801e04c3fSmrg   SWR_FORMAT fmt = mesa_to_swr_format(sf->format);
103901e04c3fSmrg
104001e04c3fSmrg   if (attachment == SWR_ATTACHMENT_STENCIL && swr->secondary.xpBaseAddress) {
104101e04c3fSmrg      swr_surface = &swr->secondary;
104201e04c3fSmrg      fmt = swr_surface->format;
104301e04c3fSmrg   }
104401e04c3fSmrg
104501e04c3fSmrg   if (rt->xpBaseAddress == swr_surface->xpBaseAddress &&
104601e04c3fSmrg       rt->format == fmt &&
104701e04c3fSmrg       rt->lod == sf->u.tex.level &&
104801e04c3fSmrg       rt->arrayIndex == sf->u.tex.first_layer)
104901e04c3fSmrg      return false;
105001e04c3fSmrg
105101e04c3fSmrg   bool need_fence = false;
105201e04c3fSmrg
105301e04c3fSmrg   /* StoreTile for changed target */
105401e04c3fSmrg   if (rt->xpBaseAddress) {
105501e04c3fSmrg      /* If changing attachment to a new target, mark tiles as
105601e04c3fSmrg       * INVALID so they are reloaded from surface. */
105701e04c3fSmrg      swr_store_render_target(&ctx->pipe, attachment, SWR_TILE_INVALID);
105801e04c3fSmrg      need_fence = true;
105901e04c3fSmrg   } else {
106001e04c3fSmrg      /* if no previous attachment, invalidate tiles that may be marked
106101e04c3fSmrg       * RESOLVED because of an old attachment */
106201e04c3fSmrg      swr_invalidate_render_target(&ctx->pipe, attachment, sf->width, sf->height);
106301e04c3fSmrg      /* no need to set fence here */
106401e04c3fSmrg   }
106501e04c3fSmrg
106601e04c3fSmrg   /* Make new attachment */
106701e04c3fSmrg   *rt = *swr_surface;
106801e04c3fSmrg   rt->format = fmt;
106901e04c3fSmrg   rt->lod = sf->u.tex.level;
107001e04c3fSmrg   rt->arrayIndex = sf->u.tex.first_layer;
107101e04c3fSmrg
107201e04c3fSmrg   return need_fence;
107301e04c3fSmrg}
107401e04c3fSmrg
107501e04c3fSmrg/*
107601e04c3fSmrg * for cases where resources are shared between contexts, invalidate
107701e04c3fSmrg * this ctx's resource. so it can be fetched fresh.  Old ctx's resource
107801e04c3fSmrg * is already stored during a flush
107901e04c3fSmrg */
108001e04c3fSmrgstatic inline void
108101e04c3fSmrgswr_invalidate_buffers_after_ctx_change(struct pipe_context *pipe)
108201e04c3fSmrg{
108301e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
108401e04c3fSmrg
108501e04c3fSmrg   for (uint32_t i = 0; i < ctx->framebuffer.nr_cbufs; i++) {
108601e04c3fSmrg      struct pipe_surface *cb = ctx->framebuffer.cbufs[i];
108701e04c3fSmrg      if (cb) {
108801e04c3fSmrg         struct swr_resource *res = swr_resource(cb->texture);
108901e04c3fSmrg         if (res->curr_pipe != pipe) {
109001e04c3fSmrg            /* if curr_pipe is NULL (first use), status should not be WRITE */
109101e04c3fSmrg            assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE));
109201e04c3fSmrg            if (res->status & SWR_RESOURCE_WRITE) {
109301e04c3fSmrg               swr_invalidate_render_target(pipe, i, cb->width, cb->height);
109401e04c3fSmrg            }
109501e04c3fSmrg         }
109601e04c3fSmrg         res->curr_pipe = pipe;
109701e04c3fSmrg      }
109801e04c3fSmrg   }
109901e04c3fSmrg   if (ctx->framebuffer.zsbuf) {
110001e04c3fSmrg      struct pipe_surface *zb = ctx->framebuffer.zsbuf;
110101e04c3fSmrg      if (zb) {
110201e04c3fSmrg         struct swr_resource *res = swr_resource(zb->texture);
110301e04c3fSmrg         if (res->curr_pipe != pipe) {
110401e04c3fSmrg            /* if curr_pipe is NULL (first use), status should not be WRITE */
110501e04c3fSmrg            assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE));
110601e04c3fSmrg            if (res->status & SWR_RESOURCE_WRITE) {
110701e04c3fSmrg               swr_invalidate_render_target(pipe, SWR_ATTACHMENT_DEPTH, zb->width, zb->height);
110801e04c3fSmrg               swr_invalidate_render_target(pipe, SWR_ATTACHMENT_STENCIL, zb->width, zb->height);
110901e04c3fSmrg            }
111001e04c3fSmrg         }
111101e04c3fSmrg         res->curr_pipe = pipe;
111201e04c3fSmrg      }
111301e04c3fSmrg   }
111401e04c3fSmrg}
111501e04c3fSmrg
111601e04c3fSmrgstatic inline void
111701e04c3fSmrgswr_user_vbuf_range(const struct pipe_draw_info *info,
111801e04c3fSmrg                    const struct swr_vertex_element_state *velems,
111901e04c3fSmrg                    const struct pipe_vertex_buffer *vb,
112001e04c3fSmrg                    uint32_t i,
112101e04c3fSmrg                    uint32_t *totelems,
112201e04c3fSmrg                    uint32_t *base,
11237ec681f3Smrg                    uint32_t *size,
11247ec681f3Smrg                    int index_bias)
112501e04c3fSmrg{
112601e04c3fSmrg   /* FIXME: The size is too large - we don't access the full extra stride. */
112701e04c3fSmrg   unsigned elems;
11287ec681f3Smrg   unsigned elem_pitch = vb->stride + velems->stream_pitch[i];
112901e04c3fSmrg   if (velems->instanced_bufs & (1U << i)) {
113001e04c3fSmrg      elems = info->instance_count / velems->min_instance_div[i] + 1;
113101e04c3fSmrg      *totelems = info->start_instance + elems;
113201e04c3fSmrg      *base = info->start_instance * vb->stride;
11337ec681f3Smrg      *size = elems * elem_pitch;
113401e04c3fSmrg   } else if (vb->stride) {
113501e04c3fSmrg      elems = info->max_index - info->min_index + 1;
11367ec681f3Smrg      *totelems = (info->max_index + (info->index_size ? index_bias : 0)) + 1;
11377ec681f3Smrg      *base = (info->min_index + (info->index_size ? index_bias : 0)) * vb->stride;
11387ec681f3Smrg      *size = elems * elem_pitch;
113901e04c3fSmrg   } else {
114001e04c3fSmrg      *totelems = 1;
114101e04c3fSmrg      *base = 0;
114201e04c3fSmrg      *size = velems->stream_pitch[i];
114301e04c3fSmrg   }
114401e04c3fSmrg}
114501e04c3fSmrg
114601e04c3fSmrgstatic void
114701e04c3fSmrgswr_update_poly_stipple(struct swr_context *ctx)
114801e04c3fSmrg{
114901e04c3fSmrg   struct swr_draw_context *pDC = &ctx->swrDC;
115001e04c3fSmrg
115101e04c3fSmrg   assert(sizeof(ctx->poly_stipple.pipe.stipple) == sizeof(pDC->polyStipple));
115201e04c3fSmrg   memcpy(pDC->polyStipple,
115301e04c3fSmrg          ctx->poly_stipple.pipe.stipple,
115401e04c3fSmrg          sizeof(ctx->poly_stipple.pipe.stipple));
115501e04c3fSmrg}
115601e04c3fSmrg
11577ec681f3Smrg
11587ec681f3Smrgstatic struct tgsi_shader_info *
11597ec681f3Smrgswr_get_last_fe(const struct swr_context *ctx)
11607ec681f3Smrg{
11617ec681f3Smrg   tgsi_shader_info *pLastFE = &ctx->vs->info.base;
11627ec681f3Smrg
11637ec681f3Smrg   if (ctx->gs) {
11647ec681f3Smrg      pLastFE = &ctx->gs->info.base;
11657ec681f3Smrg   }
11667ec681f3Smrg   else if (ctx->tes) {
11677ec681f3Smrg      pLastFE = &ctx->tes->info.base;
11687ec681f3Smrg   }
11697ec681f3Smrg   else if (ctx->tcs) {
11707ec681f3Smrg      pLastFE = &ctx->tcs->info.base;
11717ec681f3Smrg   }
11727ec681f3Smrg   return pLastFE;
11737ec681f3Smrg}
11747ec681f3Smrg
11757ec681f3Smrg
117601e04c3fSmrgvoid
117701e04c3fSmrgswr_update_derived(struct pipe_context *pipe,
11787ec681f3Smrg                   const struct pipe_draw_info *p_draw_info,
11797ec681f3Smrg                   const struct pipe_draw_start_count_bias *draw)
118001e04c3fSmrg{
118101e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
118201e04c3fSmrg   struct swr_screen *screen = swr_screen(pipe->screen);
118301e04c3fSmrg
118401e04c3fSmrg   /* When called from swr_clear (p_draw_info = null), set any null
118501e04c3fSmrg    * state-objects to the dummy state objects to prevent nullptr dereference
118601e04c3fSmrg    * in validation below.
118701e04c3fSmrg    *
118801e04c3fSmrg    * Important that this remains static for zero initialization.  These
118901e04c3fSmrg    * aren't meant to be proper state objects, just empty structs. They will
119001e04c3fSmrg    * not be written to.
119101e04c3fSmrg    *
119201e04c3fSmrg    * Shaders can't be part of the union since they contain std::unordered_map
119301e04c3fSmrg    */
119401e04c3fSmrg   static struct {
119501e04c3fSmrg      union {
119601e04c3fSmrg         struct pipe_rasterizer_state rasterizer;
119701e04c3fSmrg         struct pipe_depth_stencil_alpha_state depth_stencil;
119801e04c3fSmrg         struct swr_blend_state blend;
119901e04c3fSmrg      } state;
120001e04c3fSmrg      struct swr_vertex_shader vs;
120101e04c3fSmrg      struct swr_fragment_shader fs;
120201e04c3fSmrg   } swr_dummy;
120301e04c3fSmrg
120401e04c3fSmrg   if (!p_draw_info) {
120501e04c3fSmrg      if (!ctx->rasterizer)
120601e04c3fSmrg         ctx->rasterizer = &swr_dummy.state.rasterizer;
120701e04c3fSmrg      if (!ctx->depth_stencil)
120801e04c3fSmrg         ctx->depth_stencil = &swr_dummy.state.depth_stencil;
120901e04c3fSmrg      if (!ctx->blend)
121001e04c3fSmrg         ctx->blend = &swr_dummy.state.blend;
121101e04c3fSmrg      if (!ctx->vs)
121201e04c3fSmrg         ctx->vs = &swr_dummy.vs;
121301e04c3fSmrg      if (!ctx->fs)
121401e04c3fSmrg         ctx->fs = &swr_dummy.fs;
121501e04c3fSmrg   }
121601e04c3fSmrg
121701e04c3fSmrg   /* Update screen->pipe to current pipe context. */
121801e04c3fSmrg   screen->pipe = pipe;
121901e04c3fSmrg
122001e04c3fSmrg   /* Any state that requires dirty flags to be re-triggered sets this mask */
122101e04c3fSmrg   /* For example, user_buffer vertex and index buffers. */
122201e04c3fSmrg   unsigned post_update_dirty_flags = 0;
122301e04c3fSmrg
122401e04c3fSmrg   /* bring resources that changed context up-to-date */
122501e04c3fSmrg   swr_invalidate_buffers_after_ctx_change(pipe);
122601e04c3fSmrg
122701e04c3fSmrg   /* Render Targets */
122801e04c3fSmrg   if (ctx->dirty & SWR_NEW_FRAMEBUFFER) {
122901e04c3fSmrg      struct pipe_framebuffer_state *fb = &ctx->framebuffer;
123001e04c3fSmrg      const struct util_format_description *desc = NULL;
123101e04c3fSmrg      bool need_fence = false;
123201e04c3fSmrg
123301e04c3fSmrg      /* colorbuffer targets */
123401e04c3fSmrg      if (fb->nr_cbufs) {
123501e04c3fSmrg         for (unsigned i = 0; i < fb->nr_cbufs; ++i)
123601e04c3fSmrg            need_fence |= swr_change_rt(
123701e04c3fSmrg                  ctx, SWR_ATTACHMENT_COLOR0 + i, fb->cbufs[i]);
123801e04c3fSmrg      }
123901e04c3fSmrg      for (unsigned i = fb->nr_cbufs; i < SWR_NUM_RENDERTARGETS; ++i)
124001e04c3fSmrg         need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_COLOR0 + i, NULL);
124101e04c3fSmrg
124201e04c3fSmrg      /* depth/stencil target */
124301e04c3fSmrg      if (fb->zsbuf)
124401e04c3fSmrg         desc = util_format_description(fb->zsbuf->format);
124501e04c3fSmrg      if (fb->zsbuf && util_format_has_depth(desc))
124601e04c3fSmrg         need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_DEPTH, fb->zsbuf);
124701e04c3fSmrg      else
124801e04c3fSmrg         need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_DEPTH, NULL);
124901e04c3fSmrg
125001e04c3fSmrg      if (fb->zsbuf && util_format_has_stencil(desc))
125101e04c3fSmrg         need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_STENCIL, fb->zsbuf);
125201e04c3fSmrg      else
125301e04c3fSmrg         need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_STENCIL, NULL);
125401e04c3fSmrg
125501e04c3fSmrg      /* This fence ensures any attachment changes are resolved before the
125601e04c3fSmrg       * next draw */
125701e04c3fSmrg      if (need_fence)
125801e04c3fSmrg         swr_fence_submit(ctx, screen->flush_fence);
125901e04c3fSmrg   }
126001e04c3fSmrg
126101e04c3fSmrg   /* Raster state */
126201e04c3fSmrg   if (ctx->dirty & (SWR_NEW_RASTERIZER |
126301e04c3fSmrg                     SWR_NEW_VS | // clipping
12647ec681f3Smrg                     SWR_NEW_TES |
12657ec681f3Smrg                     SWR_NEW_TCS |
126601e04c3fSmrg                     SWR_NEW_FRAMEBUFFER)) {
126701e04c3fSmrg      pipe_rasterizer_state *rasterizer = ctx->rasterizer;
126801e04c3fSmrg      pipe_framebuffer_state *fb = &ctx->framebuffer;
126901e04c3fSmrg
127001e04c3fSmrg      SWR_RASTSTATE *rastState = &ctx->derived.rastState;
127101e04c3fSmrg      rastState->cullMode = swr_convert_cull_mode(rasterizer->cull_face);
127201e04c3fSmrg      rastState->frontWinding = rasterizer->front_ccw
127301e04c3fSmrg         ? SWR_FRONTWINDING_CCW
127401e04c3fSmrg         : SWR_FRONTWINDING_CW;
127501e04c3fSmrg      rastState->scissorEnable = rasterizer->scissor;
127601e04c3fSmrg      rastState->pointSize = rasterizer->point_size > 0.0f
127701e04c3fSmrg         ? rasterizer->point_size
127801e04c3fSmrg         : 1.0f;
127901e04c3fSmrg      rastState->lineWidth = rasterizer->line_width > 0.0f
128001e04c3fSmrg         ? rasterizer->line_width
128101e04c3fSmrg         : 1.0f;
128201e04c3fSmrg
128301e04c3fSmrg      rastState->pointParam = rasterizer->point_size_per_vertex;
128401e04c3fSmrg
128501e04c3fSmrg      rastState->pointSpriteEnable = rasterizer->sprite_coord_enable;
128601e04c3fSmrg      rastState->pointSpriteTopOrigin =
128701e04c3fSmrg         rasterizer->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT;
128801e04c3fSmrg
128901e04c3fSmrg      /* If SWR_MSAA_FORCE_ENABLE is set, turn msaa on */
129001e04c3fSmrg      if (screen->msaa_force_enable && !rasterizer->multisample) {
129101e04c3fSmrg         /* Force enable and use the value the surface was created with */
129201e04c3fSmrg         rasterizer->multisample = true;
129301e04c3fSmrg         fb->samples = swr_resource(fb->cbufs[0]->texture)->swr.numSamples;
129401e04c3fSmrg         fprintf(stderr,"msaa force enable: %d samples\n", fb->samples);
129501e04c3fSmrg      }
129601e04c3fSmrg
129701e04c3fSmrg      rastState->sampleCount = GetSampleCount(fb->samples);
129801e04c3fSmrg      rastState->forcedSampleCount = false;
129901e04c3fSmrg      rastState->bIsCenterPattern = !rasterizer->multisample;
130001e04c3fSmrg      rastState->pixelLocation = SWR_PIXEL_LOCATION_CENTER;
130101e04c3fSmrg
130201e04c3fSmrg      /* Only initialize sample positions if msaa is enabled */
130301e04c3fSmrg      if (rasterizer->multisample) {
130401e04c3fSmrg         for (uint32_t i = 0; i < fb->samples; i++) {
130501e04c3fSmrg            const uint8_t *sample = swr_sample_positions[fb->samples-1 + i];
130601e04c3fSmrg            rastState->samplePositions.SetXi(i, sample[0] << 4);
130701e04c3fSmrg            rastState->samplePositions.SetYi(i, sample[1] << 4);
130801e04c3fSmrg            rastState->samplePositions.SetX (i, sample[0] / 16.0f);
130901e04c3fSmrg            rastState->samplePositions.SetY (i, sample[1] / 16.0f);
131001e04c3fSmrg         }
131101e04c3fSmrg         rastState->samplePositions.PrecalcSampleData(fb->samples);
131201e04c3fSmrg      }
131301e04c3fSmrg
131401e04c3fSmrg      bool do_offset = false;
131501e04c3fSmrg      switch (rasterizer->fill_front) {
131601e04c3fSmrg      case PIPE_POLYGON_MODE_FILL:
131701e04c3fSmrg         do_offset = rasterizer->offset_tri;
131801e04c3fSmrg         break;
131901e04c3fSmrg      case PIPE_POLYGON_MODE_LINE:
132001e04c3fSmrg         do_offset = rasterizer->offset_line;
132101e04c3fSmrg         break;
132201e04c3fSmrg      case PIPE_POLYGON_MODE_POINT:
132301e04c3fSmrg         do_offset = rasterizer->offset_point;
132401e04c3fSmrg         break;
132501e04c3fSmrg      }
132601e04c3fSmrg
132701e04c3fSmrg      if (do_offset) {
132801e04c3fSmrg         rastState->depthBias = rasterizer->offset_units;
132901e04c3fSmrg         rastState->slopeScaledDepthBias = rasterizer->offset_scale;
133001e04c3fSmrg         rastState->depthBiasClamp = rasterizer->offset_clamp;
133101e04c3fSmrg      } else {
133201e04c3fSmrg         rastState->depthBias = 0;
133301e04c3fSmrg         rastState->slopeScaledDepthBias = 0;
133401e04c3fSmrg         rastState->depthBiasClamp = 0;
133501e04c3fSmrg      }
133601e04c3fSmrg
133701e04c3fSmrg      /* translate polygon mode, at least for the front==back case */
133801e04c3fSmrg      rastState->fillMode = swr_convert_fill_mode(rasterizer->fill_front);
133901e04c3fSmrg
134001e04c3fSmrg      struct pipe_surface *zb = fb->zsbuf;
134101e04c3fSmrg      if (zb && swr_resource(zb->texture)->has_depth)
134201e04c3fSmrg         rastState->depthFormat = swr_resource(zb->texture)->swr.format;
134301e04c3fSmrg
134401e04c3fSmrg      rastState->depthClipEnable = rasterizer->depth_clip_near;
13457ec681f3Smrg      rastState->clipEnable = rasterizer->depth_clip_near | rasterizer->depth_clip_far;
134601e04c3fSmrg      rastState->clipHalfZ = rasterizer->clip_halfz;
134701e04c3fSmrg
134801e04c3fSmrg      ctx->api.pfnSwrSetRastState(ctx->swrContext, rastState);
134901e04c3fSmrg   }
135001e04c3fSmrg
135101e04c3fSmrg   /* Viewport */
135201e04c3fSmrg   if (ctx->dirty & (SWR_NEW_VIEWPORT | SWR_NEW_FRAMEBUFFER
135301e04c3fSmrg                     | SWR_NEW_RASTERIZER)) {
13547ec681f3Smrg      pipe_viewport_state *state = &ctx->viewports[0];
135501e04c3fSmrg      pipe_framebuffer_state *fb = &ctx->framebuffer;
135601e04c3fSmrg      pipe_rasterizer_state *rasterizer = ctx->rasterizer;
135701e04c3fSmrg
13587ec681f3Smrg      SWR_VIEWPORT *vp = &ctx->derived.vp[0];
135901e04c3fSmrg      SWR_VIEWPORT_MATRICES *vpm = &ctx->derived.vpm;
136001e04c3fSmrg
13617ec681f3Smrg      for (unsigned i = 0; i < KNOB_NUM_VIEWPORTS_SCISSORS; i++) {
13627ec681f3Smrg         vp->x = state->translate[0] - state->scale[0];
13637ec681f3Smrg         vp->width = 2 * state->scale[0];
13647ec681f3Smrg         vp->y = state->translate[1] - fabs(state->scale[1]);
13657ec681f3Smrg         vp->height = 2 * fabs(state->scale[1]);
13667ec681f3Smrg         util_viewport_zmin_zmax(state, rasterizer->clip_halfz,
13677ec681f3Smrg                                 &vp->minZ, &vp->maxZ);
136801e04c3fSmrg
13697ec681f3Smrg         if (rasterizer->depth_clip_near) {
13707ec681f3Smrg            vp->minZ = 0.0f;
13717ec681f3Smrg         }
13727ec681f3Smrg
13737ec681f3Smrg         if (rasterizer->depth_clip_far) {
13747ec681f3Smrg            vp->maxZ = 1.0f;
13757ec681f3Smrg         }
13767ec681f3Smrg
13777ec681f3Smrg         vpm->m00[i] = state->scale[0];
13787ec681f3Smrg         vpm->m11[i] = state->scale[1];
13797ec681f3Smrg         vpm->m22[i] = state->scale[2];
13807ec681f3Smrg         vpm->m30[i] = state->translate[0];
13817ec681f3Smrg         vpm->m31[i] = state->translate[1];
13827ec681f3Smrg         vpm->m32[i] = state->translate[2];
13837ec681f3Smrg
13847ec681f3Smrg         /* Now that the matrix is calculated, clip the view coords to screen
13857ec681f3Smrg          * size.  OpenGL allows for -ve x,y in the viewport. */
13867ec681f3Smrg         if (vp->x < 0.0f) {
13877ec681f3Smrg            vp->width += vp->x;
13887ec681f3Smrg            vp->x = 0.0f;
13897ec681f3Smrg         }
13907ec681f3Smrg         if (vp->y < 0.0f) {
13917ec681f3Smrg            vp->height += vp->y;
13927ec681f3Smrg            vp->y = 0.0f;
13937ec681f3Smrg         }
13947ec681f3Smrg         vp->width = std::min(vp->width, (float) fb->width - vp->x);
13957ec681f3Smrg         vp->height = std::min(vp->height, (float) fb->height - vp->y);
13967ec681f3Smrg
13977ec681f3Smrg         vp++;
13987ec681f3Smrg         state++;
13997ec681f3Smrg      }
14007ec681f3Smrg      ctx->api.pfnSwrSetViewports(ctx->swrContext, KNOB_NUM_VIEWPORTS_SCISSORS,
14017ec681f3Smrg                                  &ctx->derived.vp[0], &ctx->derived.vpm);
140201e04c3fSmrg   }
140301e04c3fSmrg
140401e04c3fSmrg   /* When called from swr_clear (p_draw_info = null), render targets,
140501e04c3fSmrg    * rasterState and viewports (dependent on render targets) are the only
140601e04c3fSmrg    * necessary validation.  Defer remaining validation by setting
140701e04c3fSmrg    * post_update_dirty_flags and clear all dirty flags.  BackendState is
140801e04c3fSmrg    * still unconditionally validated below */
140901e04c3fSmrg   if (!p_draw_info) {
141001e04c3fSmrg      post_update_dirty_flags = ctx->dirty & ~(SWR_NEW_FRAMEBUFFER |
141101e04c3fSmrg                                               SWR_NEW_RASTERIZER |
141201e04c3fSmrg                                               SWR_NEW_VIEWPORT);
141301e04c3fSmrg      ctx->dirty = 0;
141401e04c3fSmrg   }
141501e04c3fSmrg
141601e04c3fSmrg   /* Scissor */
141701e04c3fSmrg   if (ctx->dirty & SWR_NEW_SCISSOR) {
14187ec681f3Smrg      ctx->api.pfnSwrSetScissorRects(ctx->swrContext, KNOB_NUM_VIEWPORTS_SCISSORS, ctx->swr_scissors);
141901e04c3fSmrg   }
142001e04c3fSmrg
142101e04c3fSmrg   /* Set vertex & index buffers */
142201e04c3fSmrg   if (ctx->dirty & SWR_NEW_VERTEX) {
142301e04c3fSmrg      const struct pipe_draw_info &info = *p_draw_info;
142401e04c3fSmrg
142501e04c3fSmrg      /* vertex buffers */
142601e04c3fSmrg      SWR_VERTEX_BUFFER_STATE swrVertexBuffers[PIPE_MAX_ATTRIBS];
142701e04c3fSmrg      for (UINT i = 0; i < ctx->num_vertex_buffers; i++) {
14287ec681f3Smrg         uint32_t size = 0, pitch = 0, elems = 0, partial_inbounds = 0;
14297ec681f3Smrg         uint32_t min_vertex_index = 0;
143001e04c3fSmrg         const uint8_t *p_data;
143101e04c3fSmrg         struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i];
143201e04c3fSmrg
143301e04c3fSmrg         pitch = vb->stride;
14349f464c52Smaya         if (vb->is_user_buffer) {
143501e04c3fSmrg            /* Client buffer
143601e04c3fSmrg             * client memory is one-time use, re-trigger SWR_NEW_VERTEX to
143701e04c3fSmrg             * revalidate on each draw */
143801e04c3fSmrg            post_update_dirty_flags |= SWR_NEW_VERTEX;
143901e04c3fSmrg
144001e04c3fSmrg            uint32_t base;
14417ec681f3Smrg            swr_user_vbuf_range(&info, ctx->velems, vb, i, &elems, &base, &size, draw->index_bias);
144201e04c3fSmrg            partial_inbounds = 0;
14437ec681f3Smrg            min_vertex_index = info.min_index + (info.index_size ? draw->index_bias : 0);
144401e04c3fSmrg
144501e04c3fSmrg            size = AlignUp(size, 4);
144601e04c3fSmrg            /* If size of client memory copy is too large, don't copy. The
144701e04c3fSmrg             * draw will access user-buffer directly and then block.  This is
144801e04c3fSmrg             * faster than queuing many large client draws. */
144901e04c3fSmrg            if (size >= screen->client_copy_limit) {
14507ec681f3Smrg               post_update_dirty_flags |= SWR_BLOCK_CLIENT_DRAW;
145101e04c3fSmrg               p_data = (const uint8_t *) vb->buffer.user;
145201e04c3fSmrg            } else {
145301e04c3fSmrg               /* Copy only needed vertices to scratch space */
145401e04c3fSmrg               const void *ptr = (const uint8_t *) vb->buffer.user + base;
145501e04c3fSmrg               ptr = (uint8_t *)swr_copy_to_scratch_space(
145601e04c3fSmrg                     ctx, &ctx->scratch->vertex_buffer, ptr, size);
145701e04c3fSmrg               p_data = (const uint8_t *)ptr - base;
145801e04c3fSmrg            }
14599f464c52Smaya         } else if (vb->buffer.resource) {
14609f464c52Smaya            /* VBO */
14619f464c52Smaya            if (!pitch) {
14629f464c52Smaya               /* If pitch=0 (ie vb->stride), buffer contains a single
14639f464c52Smaya                * constant attribute.  Use the stream_pitch which was
14649f464c52Smaya                * calculated during creation of vertex_elements_state for the
14659f464c52Smaya                * size of the attribute. */
14669f464c52Smaya               size = ctx->velems->stream_pitch[i];
14679f464c52Smaya               elems = 1;
14689f464c52Smaya               partial_inbounds = 0;
14699f464c52Smaya               min_vertex_index = 0;
14709f464c52Smaya            } else {
14719f464c52Smaya               /* size is based on buffer->width0 rather than info.max_index
14729f464c52Smaya                * to prevent having to validate VBO on each draw. */
14739f464c52Smaya               size = vb->buffer.resource->width0;
14749f464c52Smaya               elems = size / pitch;
14759f464c52Smaya               partial_inbounds = size % pitch;
14769f464c52Smaya               min_vertex_index = 0;
14779f464c52Smaya            }
14789f464c52Smaya
14799f464c52Smaya            p_data = swr_resource_data(vb->buffer.resource) + vb->buffer_offset;
14809f464c52Smaya         } else
14819f464c52Smaya            p_data = NULL;
148201e04c3fSmrg
148301e04c3fSmrg         swrVertexBuffers[i] = {0};
148401e04c3fSmrg         swrVertexBuffers[i].index = i;
148501e04c3fSmrg         swrVertexBuffers[i].pitch = pitch;
148601e04c3fSmrg         swrVertexBuffers[i].xpData = (gfxptr_t) p_data;
148701e04c3fSmrg         swrVertexBuffers[i].size = size;
148801e04c3fSmrg         swrVertexBuffers[i].minVertex = min_vertex_index;
148901e04c3fSmrg         swrVertexBuffers[i].maxVertex = elems;
149001e04c3fSmrg         swrVertexBuffers[i].partialInboundsSize = partial_inbounds;
149101e04c3fSmrg      }
149201e04c3fSmrg
149301e04c3fSmrg      ctx->api.pfnSwrSetVertexBuffers(
149401e04c3fSmrg         ctx->swrContext, ctx->num_vertex_buffers, swrVertexBuffers);
149501e04c3fSmrg
149601e04c3fSmrg      /* index buffer, if required (info passed in by swr_draw_vbo) */
149701e04c3fSmrg      SWR_FORMAT index_type = R32_UINT; /* Default for non-indexed draws */
149801e04c3fSmrg      if (info.index_size) {
149901e04c3fSmrg         const uint8_t *p_data;
150001e04c3fSmrg         uint32_t size, pitch;
150101e04c3fSmrg
150201e04c3fSmrg         pitch = info.index_size ? info.index_size : sizeof(uint32_t);
150301e04c3fSmrg         index_type = swr_convert_index_type(pitch);
150401e04c3fSmrg
150501e04c3fSmrg         if (!info.has_user_indices) {
150601e04c3fSmrg            /* VBO
150701e04c3fSmrg             * size is based on buffer->width0 rather than info.count
150801e04c3fSmrg             * to prevent having to validate VBO on each draw */
150901e04c3fSmrg            size = info.index.resource->width0;
151001e04c3fSmrg            p_data = swr_resource_data(info.index.resource);
151101e04c3fSmrg         } else {
151201e04c3fSmrg            /* Client buffer
151301e04c3fSmrg             * client memory is one-time use, re-trigger SWR_NEW_VERTEX to
151401e04c3fSmrg             * revalidate on each draw */
151501e04c3fSmrg            post_update_dirty_flags |= SWR_NEW_VERTEX;
151601e04c3fSmrg
15177ec681f3Smrg            size = draw->count * pitch;
15187ec681f3Smrg
151901e04c3fSmrg            size = AlignUp(size, 4);
152001e04c3fSmrg            /* If size of client memory copy is too large, don't copy. The
152101e04c3fSmrg             * draw will access user-buffer directly and then block.  This is
152201e04c3fSmrg             * faster than queuing many large client draws. */
152301e04c3fSmrg            if (size >= screen->client_copy_limit) {
15247ec681f3Smrg               post_update_dirty_flags |= SWR_BLOCK_CLIENT_DRAW;
15257ec681f3Smrg               p_data = (const uint8_t *) info.index.user +
15267ec681f3Smrg                        draw->start * info.index_size;
152701e04c3fSmrg            } else {
152801e04c3fSmrg               /* Copy indices to scratch space */
15297ec681f3Smrg               const void *ptr = (char*)info.index.user +
15307ec681f3Smrg                                 draw->start * info.index_size;
153101e04c3fSmrg               ptr = swr_copy_to_scratch_space(
153201e04c3fSmrg                     ctx, &ctx->scratch->index_buffer, ptr, size);
153301e04c3fSmrg               p_data = (const uint8_t *)ptr;
153401e04c3fSmrg            }
153501e04c3fSmrg         }
153601e04c3fSmrg
153701e04c3fSmrg         SWR_INDEX_BUFFER_STATE swrIndexBuffer;
153801e04c3fSmrg         swrIndexBuffer.format = swr_convert_index_type(info.index_size);
153901e04c3fSmrg         swrIndexBuffer.xpIndices = (gfxptr_t) p_data;
154001e04c3fSmrg         swrIndexBuffer.size = size;
154101e04c3fSmrg
154201e04c3fSmrg         ctx->api.pfnSwrSetIndexBuffer(ctx->swrContext, &swrIndexBuffer);
154301e04c3fSmrg      }
154401e04c3fSmrg
154501e04c3fSmrg      struct swr_vertex_element_state *velems = ctx->velems;
154601e04c3fSmrg      if (velems && velems->fsState.indexType != index_type) {
154701e04c3fSmrg         velems->fsFunc = NULL;
154801e04c3fSmrg         velems->fsState.indexType = index_type;
154901e04c3fSmrg      }
155001e04c3fSmrg   }
155101e04c3fSmrg
155201e04c3fSmrg   /* GeometryShader */
155301e04c3fSmrg   if (ctx->dirty & (SWR_NEW_GS |
155401e04c3fSmrg                     SWR_NEW_VS |
15557ec681f3Smrg                     SWR_NEW_TCS |
15567ec681f3Smrg                     SWR_NEW_TES |
155701e04c3fSmrg                     SWR_NEW_SAMPLER |
155801e04c3fSmrg                     SWR_NEW_SAMPLER_VIEW)) {
155901e04c3fSmrg      if (ctx->gs) {
156001e04c3fSmrg         swr_jit_gs_key key;
156101e04c3fSmrg         swr_generate_gs_key(key, ctx, ctx->gs);
156201e04c3fSmrg         auto search = ctx->gs->map.find(key);
156301e04c3fSmrg         PFN_GS_FUNC func;
156401e04c3fSmrg         if (search != ctx->gs->map.end()) {
156501e04c3fSmrg            func = search->second->shader;
156601e04c3fSmrg         } else {
156701e04c3fSmrg            func = swr_compile_gs(ctx, key);
156801e04c3fSmrg         }
156901e04c3fSmrg         ctx->api.pfnSwrSetGsFunc(ctx->swrContext, func);
157001e04c3fSmrg
157101e04c3fSmrg         /* JIT sampler state */
157201e04c3fSmrg         if (ctx->dirty & SWR_NEW_SAMPLER) {
157301e04c3fSmrg            swr_update_sampler_state(ctx,
157401e04c3fSmrg                                     PIPE_SHADER_GEOMETRY,
157501e04c3fSmrg                                     key.nr_samplers,
157601e04c3fSmrg                                     ctx->swrDC.samplersGS);
157701e04c3fSmrg         }
157801e04c3fSmrg
157901e04c3fSmrg         /* JIT sampler view state */
158001e04c3fSmrg         if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {
158101e04c3fSmrg            swr_update_texture_state(ctx,
158201e04c3fSmrg                                     PIPE_SHADER_GEOMETRY,
158301e04c3fSmrg                                     key.nr_sampler_views,
158401e04c3fSmrg                                     ctx->swrDC.texturesGS);
158501e04c3fSmrg         }
158601e04c3fSmrg
158701e04c3fSmrg         ctx->api.pfnSwrSetGsState(ctx->swrContext, &ctx->gs->gsState);
158801e04c3fSmrg      } else {
158901e04c3fSmrg         SWR_GS_STATE state = { 0 };
159001e04c3fSmrg         ctx->api.pfnSwrSetGsState(ctx->swrContext, &state);
159101e04c3fSmrg         ctx->api.pfnSwrSetGsFunc(ctx->swrContext, NULL);
159201e04c3fSmrg      }
159301e04c3fSmrg   }
159401e04c3fSmrg
15957ec681f3Smrg   // We may need to restore tessellation state
15967ec681f3Smrg   // This restored state may be however overwritten
15977ec681f3Smrg   // during shader compilation
15987ec681f3Smrg   if (ctx->dirty & SWR_NEW_TS) {
15997ec681f3Smrg      if (ctx->tes != nullptr) {
16007ec681f3Smrg         ctx->tsState = ctx->tes->ts_state;
16017ec681f3Smrg         ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState);
16027ec681f3Smrg      } else {
16037ec681f3Smrg         SWR_TS_STATE state = { 0 };
16047ec681f3Smrg         ctx->api.pfnSwrSetTsState(ctx->swrContext, &state);
16057ec681f3Smrg      }
16067ec681f3Smrg   }
16077ec681f3Smrg
16087ec681f3Smrg   // Tessellation Evaluation Shader
16097ec681f3Smrg   // Compile TES first, because TCS is optional
16107ec681f3Smrg   if (ctx->dirty & (SWR_NEW_GS |
16117ec681f3Smrg                     SWR_NEW_VS |
16127ec681f3Smrg                     SWR_NEW_TCS |
16137ec681f3Smrg                     SWR_NEW_TES |
161401e04c3fSmrg                     SWR_NEW_SAMPLER |
16157ec681f3Smrg                     SWR_NEW_SAMPLER_VIEW)) {
16167ec681f3Smrg      if (ctx->tes) {
16177ec681f3Smrg         swr_jit_tes_key key;
16187ec681f3Smrg         swr_generate_tes_key(key, ctx, ctx->tes);
16197ec681f3Smrg
16207ec681f3Smrg         auto search = ctx->tes->map.find(key);
16217ec681f3Smrg         PFN_TES_FUNC func;
16227ec681f3Smrg         if (search != ctx->tes->map.end()) {
16237ec681f3Smrg            func = search->second->shader;
16247ec681f3Smrg         } else {
16257ec681f3Smrg            func = swr_compile_tes(ctx, key);
16267ec681f3Smrg         }
16277ec681f3Smrg
16287ec681f3Smrg         ctx->api.pfnSwrSetDsFunc(ctx->swrContext, func);
16297ec681f3Smrg
16307ec681f3Smrg         /* JIT sampler state */
16317ec681f3Smrg         if (ctx->dirty & SWR_NEW_SAMPLER) {
16327ec681f3Smrg            swr_update_sampler_state(ctx,
16337ec681f3Smrg                                     PIPE_SHADER_TESS_EVAL,
16347ec681f3Smrg                                     key.nr_samplers,
16357ec681f3Smrg                                     ctx->swrDC.samplersTES);
16367ec681f3Smrg         }
16377ec681f3Smrg
16387ec681f3Smrg         /* JIT sampler view state */
16397ec681f3Smrg         if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {
16407ec681f3Smrg            swr_update_texture_state(ctx,
16417ec681f3Smrg                                     PIPE_SHADER_TESS_EVAL,
16427ec681f3Smrg                                     key.nr_sampler_views,
16437ec681f3Smrg                                     ctx->swrDC.texturesTES);
16447ec681f3Smrg         }
16457ec681f3Smrg
16467ec681f3Smrg         // Update tessellation state in case it's been updated
16477ec681f3Smrg         ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState);
16487ec681f3Smrg      } else {
16497ec681f3Smrg         ctx->api.pfnSwrSetDsFunc(ctx->swrContext, NULL);
16507ec681f3Smrg      }
16517ec681f3Smrg   }
16527ec681f3Smrg
16537ec681f3Smrg   /* Tessellation Control Shader */
16547ec681f3Smrg   if (ctx->dirty & (SWR_NEW_GS |
16557ec681f3Smrg                     SWR_NEW_VS |
16567ec681f3Smrg                     SWR_NEW_TCS |
16577ec681f3Smrg                     SWR_NEW_TES |
16587ec681f3Smrg                     SWR_NEW_SAMPLER |
16597ec681f3Smrg                     SWR_NEW_SAMPLER_VIEW)) {
16607ec681f3Smrg      if (ctx->tcs) {
16617ec681f3Smrg         ctx->tcs->vertices_per_patch = ctx->patch_vertices;
16627ec681f3Smrg
16637ec681f3Smrg         swr_jit_tcs_key key;
16647ec681f3Smrg         swr_generate_tcs_key(key, ctx, ctx->tcs);
16657ec681f3Smrg
16667ec681f3Smrg         auto search = ctx->tcs->map.find(key);
16677ec681f3Smrg         PFN_TCS_FUNC func;
16687ec681f3Smrg         if (search != ctx->tcs->map.end()) {
16697ec681f3Smrg            func = search->second->shader;
16707ec681f3Smrg         } else {
16717ec681f3Smrg            func = swr_compile_tcs(ctx, key);
16727ec681f3Smrg         }
16737ec681f3Smrg
16747ec681f3Smrg         ctx->api.pfnSwrSetHsFunc(ctx->swrContext, func);
16757ec681f3Smrg
16767ec681f3Smrg         /* JIT sampler state */
16777ec681f3Smrg         if (ctx->dirty & SWR_NEW_SAMPLER) {
16787ec681f3Smrg            swr_update_sampler_state(ctx,
16797ec681f3Smrg                                     PIPE_SHADER_TESS_CTRL,
16807ec681f3Smrg                                     key.nr_samplers,
16817ec681f3Smrg                                     ctx->swrDC.samplersTCS);
16827ec681f3Smrg         }
16837ec681f3Smrg
16847ec681f3Smrg         /* JIT sampler view state */
16857ec681f3Smrg         if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {
16867ec681f3Smrg            swr_update_texture_state(ctx,
16877ec681f3Smrg                                     PIPE_SHADER_TESS_CTRL,
16887ec681f3Smrg                                     key.nr_sampler_views,
16897ec681f3Smrg                                     ctx->swrDC.texturesTCS);
16907ec681f3Smrg         }
16917ec681f3Smrg
16927ec681f3Smrg         // Update tessellation state in case it's been updated
16937ec681f3Smrg         ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState);
16947ec681f3Smrg      } else {
16957ec681f3Smrg         ctx->api.pfnSwrSetHsFunc(ctx->swrContext, NULL);
16967ec681f3Smrg      }
16977ec681f3Smrg   }
16987ec681f3Smrg
16997ec681f3Smrg   /* VertexShader */
17007ec681f3Smrg   if (ctx->dirty
17017ec681f3Smrg       & (SWR_NEW_VS | SWR_NEW_RASTERIZER | // for clip planes
17027ec681f3Smrg          SWR_NEW_SAMPLER | SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {
170301e04c3fSmrg      swr_jit_vs_key key;
170401e04c3fSmrg      swr_generate_vs_key(key, ctx, ctx->vs);
170501e04c3fSmrg      auto search = ctx->vs->map.find(key);
170601e04c3fSmrg      PFN_VERTEX_FUNC func;
170701e04c3fSmrg      if (search != ctx->vs->map.end()) {
170801e04c3fSmrg         func = search->second->shader;
170901e04c3fSmrg      } else {
171001e04c3fSmrg         func = swr_compile_vs(ctx, key);
171101e04c3fSmrg      }
171201e04c3fSmrg      ctx->api.pfnSwrSetVertexFunc(ctx->swrContext, func);
171301e04c3fSmrg
171401e04c3fSmrg      /* JIT sampler state */
171501e04c3fSmrg      if (ctx->dirty & SWR_NEW_SAMPLER) {
17167ec681f3Smrg         swr_update_sampler_state(
17177ec681f3Smrg            ctx, PIPE_SHADER_VERTEX, key.nr_samplers, ctx->swrDC.samplersVS);
171801e04c3fSmrg      }
171901e04c3fSmrg
172001e04c3fSmrg      /* JIT sampler view state */
172101e04c3fSmrg      if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {
172201e04c3fSmrg         swr_update_texture_state(ctx,
172301e04c3fSmrg                                  PIPE_SHADER_VERTEX,
172401e04c3fSmrg                                  key.nr_sampler_views,
172501e04c3fSmrg                                  ctx->swrDC.texturesVS);
172601e04c3fSmrg      }
172701e04c3fSmrg   }
172801e04c3fSmrg
172901e04c3fSmrg   /* work around the fact that poly stipple also affects lines */
173001e04c3fSmrg   /* and points, since we rasterize them as triangles, too */
173101e04c3fSmrg   /* Has to be before fragment shader, since it sets SWR_NEW_FS */
173201e04c3fSmrg   if (p_draw_info) {
173301e04c3fSmrg      bool new_prim_is_poly =
17347ec681f3Smrg         (u_reduced_prim((enum pipe_prim_type)p_draw_info->mode) == PIPE_PRIM_TRIANGLES) &&
173501e04c3fSmrg         (ctx->derived.rastState.fillMode == SWR_FILLMODE_SOLID);
173601e04c3fSmrg      if (new_prim_is_poly != ctx->poly_stipple.prim_is_poly) {
173701e04c3fSmrg         ctx->dirty |= SWR_NEW_FS;
173801e04c3fSmrg         ctx->poly_stipple.prim_is_poly = new_prim_is_poly;
173901e04c3fSmrg      }
174001e04c3fSmrg   }
174101e04c3fSmrg
174201e04c3fSmrg   /* FragmentShader */
174301e04c3fSmrg   if (ctx->dirty & (SWR_NEW_FS |
174401e04c3fSmrg                     SWR_NEW_VS |
174501e04c3fSmrg                     SWR_NEW_GS |
17467ec681f3Smrg                     SWR_NEW_TES |
17477ec681f3Smrg                     SWR_NEW_TCS |
174801e04c3fSmrg                     SWR_NEW_RASTERIZER |
174901e04c3fSmrg                     SWR_NEW_SAMPLER |
175001e04c3fSmrg                     SWR_NEW_SAMPLER_VIEW |
175101e04c3fSmrg                     SWR_NEW_FRAMEBUFFER)) {
175201e04c3fSmrg      swr_jit_fs_key key;
175301e04c3fSmrg      swr_generate_fs_key(key, ctx, ctx->fs);
175401e04c3fSmrg      auto search = ctx->fs->map.find(key);
175501e04c3fSmrg      PFN_PIXEL_KERNEL func;
175601e04c3fSmrg      if (search != ctx->fs->map.end()) {
175701e04c3fSmrg         func = search->second->shader;
175801e04c3fSmrg      } else {
175901e04c3fSmrg         func = swr_compile_fs(ctx, key);
176001e04c3fSmrg      }
176101e04c3fSmrg      SWR_PS_STATE psState = {0};
176201e04c3fSmrg      psState.pfnPixelShader = func;
176301e04c3fSmrg      psState.killsPixel = ctx->fs->info.base.uses_kill;
176401e04c3fSmrg      psState.inputCoverage = SWR_INPUT_COVERAGE_NORMAL;
176501e04c3fSmrg      psState.writesODepth = ctx->fs->info.base.writes_z;
176601e04c3fSmrg      psState.usesSourceDepth = ctx->fs->info.base.reads_z;
176701e04c3fSmrg      psState.shadingRate = SWR_SHADING_RATE_PIXEL;
176801e04c3fSmrg      psState.renderTargetMask = (1 << ctx->framebuffer.nr_cbufs) - 1;
176901e04c3fSmrg      psState.posOffset = SWR_PS_POSITION_SAMPLE_NONE;
177001e04c3fSmrg      uint32_t barycentricsMask = 0;
177101e04c3fSmrg#if 0
177201e04c3fSmrg      // when we switch to mesa-master
177301e04c3fSmrg      if (ctx->fs->info.base.uses_persp_center ||
177401e04c3fSmrg          ctx->fs->info.base.uses_linear_center)
177501e04c3fSmrg         barycentricsMask |= SWR_BARYCENTRIC_PER_PIXEL_MASK;
177601e04c3fSmrg      if (ctx->fs->info.base.uses_persp_centroid ||
177701e04c3fSmrg          ctx->fs->info.base.uses_linear_centroid)
177801e04c3fSmrg         barycentricsMask |= SWR_BARYCENTRIC_CENTROID_MASK;
177901e04c3fSmrg      if (ctx->fs->info.base.uses_persp_sample ||
178001e04c3fSmrg          ctx->fs->info.base.uses_linear_sample)
178101e04c3fSmrg         barycentricsMask |= SWR_BARYCENTRIC_PER_SAMPLE_MASK;
178201e04c3fSmrg#else
178301e04c3fSmrg      for (unsigned i = 0; i < ctx->fs->info.base.num_inputs; i++) {
178401e04c3fSmrg         switch (ctx->fs->info.base.input_interpolate_loc[i]) {
178501e04c3fSmrg         case TGSI_INTERPOLATE_LOC_CENTER:
178601e04c3fSmrg            barycentricsMask |= SWR_BARYCENTRIC_PER_PIXEL_MASK;
178701e04c3fSmrg            break;
178801e04c3fSmrg         case TGSI_INTERPOLATE_LOC_CENTROID:
178901e04c3fSmrg            barycentricsMask |= SWR_BARYCENTRIC_CENTROID_MASK;
179001e04c3fSmrg            break;
179101e04c3fSmrg         case TGSI_INTERPOLATE_LOC_SAMPLE:
179201e04c3fSmrg            barycentricsMask |= SWR_BARYCENTRIC_PER_SAMPLE_MASK;
179301e04c3fSmrg            break;
179401e04c3fSmrg         }
179501e04c3fSmrg      }
179601e04c3fSmrg#endif
179701e04c3fSmrg      psState.barycentricsMask = barycentricsMask;
179801e04c3fSmrg      psState.usesUAV = false; // XXX
179901e04c3fSmrg      psState.forceEarlyZ = false;
180001e04c3fSmrg      ctx->api.pfnSwrSetPixelShaderState(ctx->swrContext, &psState);
180101e04c3fSmrg
180201e04c3fSmrg      /* JIT sampler state */
180301e04c3fSmrg      if (ctx->dirty & (SWR_NEW_SAMPLER |
180401e04c3fSmrg                        SWR_NEW_FS)) {
180501e04c3fSmrg         swr_update_sampler_state(ctx,
180601e04c3fSmrg                                  PIPE_SHADER_FRAGMENT,
180701e04c3fSmrg                                  key.nr_samplers,
180801e04c3fSmrg                                  ctx->swrDC.samplersFS);
180901e04c3fSmrg      }
181001e04c3fSmrg
181101e04c3fSmrg      /* JIT sampler view state */
181201e04c3fSmrg      if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW |
181301e04c3fSmrg                        SWR_NEW_FRAMEBUFFER |
181401e04c3fSmrg                        SWR_NEW_FS)) {
181501e04c3fSmrg         swr_update_texture_state(ctx,
181601e04c3fSmrg                                  PIPE_SHADER_FRAGMENT,
181701e04c3fSmrg                                  key.nr_sampler_views,
181801e04c3fSmrg                                  ctx->swrDC.texturesFS);
181901e04c3fSmrg      }
182001e04c3fSmrg   }
182101e04c3fSmrg
182201e04c3fSmrg
182301e04c3fSmrg   /* VertexShader Constants */
182401e04c3fSmrg   if (ctx->dirty & SWR_NEW_VSCONSTANTS) {
182501e04c3fSmrg      swr_update_constants(ctx, PIPE_SHADER_VERTEX);
182601e04c3fSmrg   }
182701e04c3fSmrg
182801e04c3fSmrg   /* FragmentShader Constants */
182901e04c3fSmrg   if (ctx->dirty & SWR_NEW_FSCONSTANTS) {
183001e04c3fSmrg      swr_update_constants(ctx, PIPE_SHADER_FRAGMENT);
183101e04c3fSmrg   }
183201e04c3fSmrg
183301e04c3fSmrg   /* GeometryShader Constants */
183401e04c3fSmrg   if (ctx->dirty & SWR_NEW_GSCONSTANTS) {
183501e04c3fSmrg      swr_update_constants(ctx, PIPE_SHADER_GEOMETRY);
183601e04c3fSmrg   }
183701e04c3fSmrg
18387ec681f3Smrg   /* Tessellation Control Shader Constants */
18397ec681f3Smrg   if (ctx->dirty & SWR_NEW_TCSCONSTANTS) {
18407ec681f3Smrg      swr_update_constants(ctx, PIPE_SHADER_TESS_CTRL);
18417ec681f3Smrg   }
18427ec681f3Smrg
18437ec681f3Smrg   /* Tessellation Evaluation Shader Constants */
18447ec681f3Smrg   if (ctx->dirty & SWR_NEW_TESCONSTANTS) {
18457ec681f3Smrg      swr_update_constants(ctx, PIPE_SHADER_TESS_EVAL);
18467ec681f3Smrg   }
18477ec681f3Smrg
184801e04c3fSmrg   /* Depth/stencil state */
184901e04c3fSmrg   if (ctx->dirty & (SWR_NEW_DEPTH_STENCIL_ALPHA | SWR_NEW_FRAMEBUFFER)) {
18507ec681f3Smrg      struct pipe_depth_stencil_alpha_state *depth = ctx->depth_stencil;
18517ec681f3Smrg      struct pipe_stencil_state *stencil = depth->stencil;
185201e04c3fSmrg      SWR_DEPTH_STENCIL_STATE depthStencilState = {{0}};
185301e04c3fSmrg      SWR_DEPTH_BOUNDS_STATE depthBoundsState = {0};
185401e04c3fSmrg
185501e04c3fSmrg      /* XXX, incomplete.  Need to flesh out stencil & alpha test state
185601e04c3fSmrg      struct pipe_stencil_state *front_stencil =
185701e04c3fSmrg      ctx->depth_stencil.stencil[0];
185801e04c3fSmrg      struct pipe_stencil_state *back_stencil = ctx->depth_stencil.stencil[1];
185901e04c3fSmrg      */
186001e04c3fSmrg      if (stencil[0].enabled) {
186101e04c3fSmrg         depthStencilState.stencilWriteEnable = 1;
186201e04c3fSmrg         depthStencilState.stencilTestEnable = 1;
186301e04c3fSmrg         depthStencilState.stencilTestFunc =
186401e04c3fSmrg            swr_convert_depth_func(stencil[0].func);
186501e04c3fSmrg
186601e04c3fSmrg         depthStencilState.stencilPassDepthPassOp =
186701e04c3fSmrg            swr_convert_stencil_op(stencil[0].zpass_op);
186801e04c3fSmrg         depthStencilState.stencilPassDepthFailOp =
186901e04c3fSmrg            swr_convert_stencil_op(stencil[0].zfail_op);
187001e04c3fSmrg         depthStencilState.stencilFailOp =
187101e04c3fSmrg            swr_convert_stencil_op(stencil[0].fail_op);
187201e04c3fSmrg         depthStencilState.stencilWriteMask = stencil[0].writemask;
187301e04c3fSmrg         depthStencilState.stencilTestMask = stencil[0].valuemask;
187401e04c3fSmrg         depthStencilState.stencilRefValue = ctx->stencil_ref.ref_value[0];
187501e04c3fSmrg      }
187601e04c3fSmrg      if (stencil[1].enabled) {
187701e04c3fSmrg         depthStencilState.doubleSidedStencilTestEnable = 1;
187801e04c3fSmrg
187901e04c3fSmrg         depthStencilState.backfaceStencilTestFunc =
188001e04c3fSmrg            swr_convert_depth_func(stencil[1].func);
188101e04c3fSmrg
188201e04c3fSmrg         depthStencilState.backfaceStencilPassDepthPassOp =
188301e04c3fSmrg            swr_convert_stencil_op(stencil[1].zpass_op);
188401e04c3fSmrg         depthStencilState.backfaceStencilPassDepthFailOp =
188501e04c3fSmrg            swr_convert_stencil_op(stencil[1].zfail_op);
188601e04c3fSmrg         depthStencilState.backfaceStencilFailOp =
188701e04c3fSmrg            swr_convert_stencil_op(stencil[1].fail_op);
188801e04c3fSmrg         depthStencilState.backfaceStencilWriteMask = stencil[1].writemask;
188901e04c3fSmrg         depthStencilState.backfaceStencilTestMask = stencil[1].valuemask;
189001e04c3fSmrg
189101e04c3fSmrg         depthStencilState.backfaceStencilRefValue =
189201e04c3fSmrg            ctx->stencil_ref.ref_value[1];
189301e04c3fSmrg      }
189401e04c3fSmrg
18957ec681f3Smrg      depthStencilState.depthTestEnable = depth->depth_enabled;
18967ec681f3Smrg      depthStencilState.depthTestFunc = swr_convert_depth_func(depth->depth_func);
18977ec681f3Smrg      depthStencilState.depthWriteEnable = depth->depth_writemask;
189801e04c3fSmrg      ctx->api.pfnSwrSetDepthStencilState(ctx->swrContext, &depthStencilState);
189901e04c3fSmrg
19007ec681f3Smrg      depthBoundsState.depthBoundsTestEnable = depth->depth_bounds_test;
19017ec681f3Smrg      depthBoundsState.depthBoundsTestMinValue = depth->depth_bounds_min;
19027ec681f3Smrg      depthBoundsState.depthBoundsTestMaxValue = depth->depth_bounds_max;
190301e04c3fSmrg      ctx->api.pfnSwrSetDepthBoundsState(ctx->swrContext, &depthBoundsState);
190401e04c3fSmrg   }
190501e04c3fSmrg
190601e04c3fSmrg   /* Blend State */
190701e04c3fSmrg   if (ctx->dirty & (SWR_NEW_BLEND |
190801e04c3fSmrg                     SWR_NEW_RASTERIZER |
190901e04c3fSmrg                     SWR_NEW_FRAMEBUFFER |
191001e04c3fSmrg                     SWR_NEW_DEPTH_STENCIL_ALPHA)) {
191101e04c3fSmrg      struct pipe_framebuffer_state *fb = &ctx->framebuffer;
191201e04c3fSmrg
191301e04c3fSmrg      SWR_BLEND_STATE blendState;
191401e04c3fSmrg      memcpy(&blendState, &ctx->blend->blendState, sizeof(blendState));
191501e04c3fSmrg      blendState.constantColor[0] = ctx->blend_color.color[0];
191601e04c3fSmrg      blendState.constantColor[1] = ctx->blend_color.color[1];
191701e04c3fSmrg      blendState.constantColor[2] = ctx->blend_color.color[2];
191801e04c3fSmrg      blendState.constantColor[3] = ctx->blend_color.color[3];
191901e04c3fSmrg      blendState.alphaTestReference =
19207ec681f3Smrg         *((uint32_t*)&ctx->depth_stencil->alpha_ref_value);
192101e04c3fSmrg
192201e04c3fSmrg      blendState.sampleMask = ctx->sample_mask;
192301e04c3fSmrg      blendState.sampleCount = GetSampleCount(fb->samples);
192401e04c3fSmrg
192501e04c3fSmrg      /* If there are no color buffers bound, disable writes on RT0
192601e04c3fSmrg       * and skip loop */
192701e04c3fSmrg      if (fb->nr_cbufs == 0) {
192801e04c3fSmrg         blendState.renderTarget[0].writeDisableRed = 1;
192901e04c3fSmrg         blendState.renderTarget[0].writeDisableGreen = 1;
193001e04c3fSmrg         blendState.renderTarget[0].writeDisableBlue = 1;
193101e04c3fSmrg         blendState.renderTarget[0].writeDisableAlpha = 1;
193201e04c3fSmrg         ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, 0, NULL);
193301e04c3fSmrg      }
193401e04c3fSmrg      else
193501e04c3fSmrg         for (int target = 0;
193601e04c3fSmrg               target < std::min(SWR_NUM_RENDERTARGETS,
193701e04c3fSmrg                                 PIPE_MAX_COLOR_BUFS);
193801e04c3fSmrg               target++) {
193901e04c3fSmrg            if (!fb->cbufs[target])
194001e04c3fSmrg               continue;
194101e04c3fSmrg
194201e04c3fSmrg            struct swr_resource *colorBuffer =
194301e04c3fSmrg               swr_resource(fb->cbufs[target]->texture);
194401e04c3fSmrg
194501e04c3fSmrg            BLEND_COMPILE_STATE compileState;
194601e04c3fSmrg            memset(&compileState, 0, sizeof(compileState));
194701e04c3fSmrg            compileState.format = colorBuffer->swr.format;
194801e04c3fSmrg            memcpy(&compileState.blendState,
194901e04c3fSmrg                   &ctx->blend->compileState[target],
195001e04c3fSmrg                   sizeof(compileState.blendState));
195101e04c3fSmrg
195201e04c3fSmrg            const SWR_FORMAT_INFO& info = GetFormatInfo(compileState.format);
195301e04c3fSmrg            if (compileState.blendState.logicOpEnable &&
195401e04c3fSmrg                ((info.type[0] == SWR_TYPE_FLOAT) || info.isSRGB)) {
195501e04c3fSmrg               compileState.blendState.logicOpEnable = false;
195601e04c3fSmrg            }
195701e04c3fSmrg
195801e04c3fSmrg            if (info.type[0] == SWR_TYPE_SINT || info.type[0] == SWR_TYPE_UINT)
195901e04c3fSmrg               compileState.blendState.blendEnable = false;
196001e04c3fSmrg
196101e04c3fSmrg            if (compileState.blendState.blendEnable == false &&
196201e04c3fSmrg                compileState.blendState.logicOpEnable == false &&
19637ec681f3Smrg                ctx->depth_stencil->alpha_enabled == 0) {
196401e04c3fSmrg               ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, target, NULL);
196501e04c3fSmrg               continue;
196601e04c3fSmrg            }
196701e04c3fSmrg
196801e04c3fSmrg            compileState.desc.alphaTestEnable =
19697ec681f3Smrg               ctx->depth_stencil->alpha_enabled;
197001e04c3fSmrg            compileState.desc.independentAlphaBlendEnable =
197101e04c3fSmrg               (compileState.blendState.sourceBlendFactor !=
197201e04c3fSmrg                compileState.blendState.sourceAlphaBlendFactor) ||
197301e04c3fSmrg               (compileState.blendState.destBlendFactor !=
197401e04c3fSmrg                compileState.blendState.destAlphaBlendFactor) ||
197501e04c3fSmrg               (compileState.blendState.colorBlendFunc !=
197601e04c3fSmrg                compileState.blendState.alphaBlendFunc);
197701e04c3fSmrg            compileState.desc.alphaToCoverageEnable =
197801e04c3fSmrg               ctx->blend->pipe.alpha_to_coverage;
197901e04c3fSmrg            compileState.desc.sampleMaskEnable = (blendState.sampleMask != 0);
198001e04c3fSmrg            compileState.desc.numSamples = fb->samples;
198101e04c3fSmrg
198201e04c3fSmrg            compileState.alphaTestFunction =
19837ec681f3Smrg               swr_convert_depth_func(ctx->depth_stencil->alpha_func);
198401e04c3fSmrg            compileState.alphaTestFormat = ALPHA_TEST_FLOAT32; // xxx
198501e04c3fSmrg
198601e04c3fSmrg            compileState.Canonicalize();
19877ec681f3Smrg
198801e04c3fSmrg            PFN_BLEND_JIT_FUNC func = NULL;
198901e04c3fSmrg            auto search = ctx->blendJIT->find(compileState);
199001e04c3fSmrg            if (search != ctx->blendJIT->end()) {
199101e04c3fSmrg               func = search->second;
199201e04c3fSmrg            } else {
199301e04c3fSmrg               HANDLE hJitMgr = screen->hJitMgr;
199401e04c3fSmrg               func = JitCompileBlend(hJitMgr, compileState);
199501e04c3fSmrg               debug_printf("BLEND shader %p\n", func);
199601e04c3fSmrg               assert(func && "Error: BlendShader = NULL");
199701e04c3fSmrg
199801e04c3fSmrg               ctx->blendJIT->insert(std::make_pair(compileState, func));
199901e04c3fSmrg            }
200001e04c3fSmrg            ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, target, func);
200101e04c3fSmrg         }
200201e04c3fSmrg
200301e04c3fSmrg      ctx->api.pfnSwrSetBlendState(ctx->swrContext, &blendState);
200401e04c3fSmrg   }
200501e04c3fSmrg
200601e04c3fSmrg   if (ctx->dirty & SWR_NEW_STIPPLE) {
200701e04c3fSmrg      swr_update_poly_stipple(ctx);
200801e04c3fSmrg   }
200901e04c3fSmrg
20107ec681f3Smrg   if (ctx->dirty & (SWR_NEW_VS | SWR_NEW_TCS | SWR_NEW_TES | SWR_NEW_SO | SWR_NEW_RASTERIZER)) {
201101e04c3fSmrg      ctx->vs->soState.rasterizerDisable =
201201e04c3fSmrg         ctx->rasterizer->rasterizer_discard;
201301e04c3fSmrg      ctx->api.pfnSwrSetSoState(ctx->swrContext, &ctx->vs->soState);
201401e04c3fSmrg
201501e04c3fSmrg      pipe_stream_output_info *stream_output = &ctx->vs->pipe.stream_output;
201601e04c3fSmrg
20177ec681f3Smrg      for (uint32_t i = 0; i < MAX_SO_STREAMS; i++) {
201801e04c3fSmrg         SWR_STREAMOUT_BUFFER buffer = {0};
20197ec681f3Smrg         if (ctx->so_targets[i]) {
20207ec681f3Smrg             buffer.enable = true;
20217ec681f3Smrg             buffer.pBuffer =
20227ec681f3Smrg                (gfxptr_t)(swr_resource_data(ctx->so_targets[i]->buffer) +
20237ec681f3Smrg                             ctx->so_targets[i]->buffer_offset);
20247ec681f3Smrg             buffer.bufferSize = ctx->so_targets[i]->buffer_size >> 2;
20257ec681f3Smrg             buffer.pitch = stream_output->stride[i];
20267ec681f3Smrg             buffer.streamOffset = 0;
20277ec681f3Smrg	 }
202801e04c3fSmrg
202901e04c3fSmrg         ctx->api.pfnSwrSetSoBuffers(ctx->swrContext, &buffer, i);
203001e04c3fSmrg      }
203101e04c3fSmrg   }
203201e04c3fSmrg
20337ec681f3Smrg
203401e04c3fSmrg   if (ctx->dirty & (SWR_NEW_CLIP | SWR_NEW_RASTERIZER | SWR_NEW_VS)) {
203501e04c3fSmrg      // shader exporting clip distances overrides all user clip planes
203601e04c3fSmrg      if (ctx->rasterizer->clip_plane_enable &&
20377ec681f3Smrg          !swr_get_last_fe(ctx)->num_written_clipdistance)
203801e04c3fSmrg      {
203901e04c3fSmrg         swr_draw_context *pDC = &ctx->swrDC;
204001e04c3fSmrg         memcpy(pDC->userClipPlanes,
204101e04c3fSmrg                ctx->clip.ucp,
204201e04c3fSmrg                sizeof(pDC->userClipPlanes));
204301e04c3fSmrg      }
204401e04c3fSmrg   }
204501e04c3fSmrg
204601e04c3fSmrg   // set up backend state
204701e04c3fSmrg   SWR_BACKEND_STATE backendState = {0};
204801e04c3fSmrg   if (ctx->gs) {
204901e04c3fSmrg      backendState.numAttributes = ctx->gs->info.base.num_outputs - 1;
20507ec681f3Smrg   } else
20517ec681f3Smrg   if (ctx->tes) {
20527ec681f3Smrg      backendState.numAttributes = ctx->tes->info.base.num_outputs - 1;
20537ec681f3Smrg      // no case for TCS, because if TCS is active, TES must be active
20547ec681f3Smrg      // as well - pipeline stages after tessellation does not support patches
20557ec681f3Smrg   }  else {
205601e04c3fSmrg      backendState.numAttributes = ctx->vs->info.base.num_outputs - 1;
205701e04c3fSmrg      if (ctx->fs->info.base.uses_primid) {
205801e04c3fSmrg         backendState.numAttributes++;
205901e04c3fSmrg         backendState.swizzleEnable = true;
206001e04c3fSmrg         for (unsigned i = 0; i < sizeof(backendState.numComponents); i++) {
206101e04c3fSmrg            backendState.swizzleMap[i].sourceAttrib = i;
206201e04c3fSmrg         }
206301e04c3fSmrg         backendState.swizzleMap[ctx->vs->info.base.num_outputs - 1].constantSource =
206401e04c3fSmrg            SWR_CONSTANT_SOURCE_PRIM_ID;
206501e04c3fSmrg         backendState.swizzleMap[ctx->vs->info.base.num_outputs - 1].componentOverrideMask = 1;
206601e04c3fSmrg      }
206701e04c3fSmrg   }
206801e04c3fSmrg   if (ctx->rasterizer->sprite_coord_enable)
206901e04c3fSmrg      backendState.numAttributes++;
207001e04c3fSmrg
207101e04c3fSmrg   backendState.numAttributes = std::min((size_t)backendState.numAttributes,
207201e04c3fSmrg                                         sizeof(backendState.numComponents));
207301e04c3fSmrg   for (unsigned i = 0; i < backendState.numAttributes; i++)
207401e04c3fSmrg      backendState.numComponents[i] = 4;
207501e04c3fSmrg   backendState.constantInterpolationMask = ctx->fs->constantMask |
207601e04c3fSmrg      (ctx->rasterizer->flatshade ? ctx->fs->flatConstantMask : 0);
207701e04c3fSmrg   backendState.pointSpriteTexCoordMask = ctx->fs->pointSpriteMask;
207801e04c3fSmrg
20797ec681f3Smrg   struct tgsi_shader_info *pLastFE = swr_get_last_fe(ctx);
20807ec681f3Smrg
208101e04c3fSmrg   backendState.readRenderTargetArrayIndex = pLastFE->writes_layer;
208201e04c3fSmrg   backendState.readViewportArrayIndex = pLastFE->writes_viewport_index;
208301e04c3fSmrg   backendState.vertexAttribOffset = VERTEX_ATTRIB_START_SLOT; // TODO: optimize
208401e04c3fSmrg
208501e04c3fSmrg   backendState.clipDistanceMask =
20867ec681f3Smrg      pLastFE->num_written_clipdistance ?
20877ec681f3Smrg      pLastFE->clipdist_writemask & ctx->rasterizer->clip_plane_enable :
208801e04c3fSmrg      ctx->rasterizer->clip_plane_enable;
208901e04c3fSmrg
209001e04c3fSmrg   backendState.cullDistanceMask =
20917ec681f3Smrg      pLastFE->culldist_writemask << pLastFE->num_written_clipdistance;
209201e04c3fSmrg
209301e04c3fSmrg   // Assume old layout of SGV, POSITION, CLIPCULL, ATTRIB
209401e04c3fSmrg   backendState.vertexClipCullOffset = backendState.vertexAttribOffset - 2;
209501e04c3fSmrg
209601e04c3fSmrg   ctx->api.pfnSwrSetBackendState(ctx->swrContext, &backendState);
209701e04c3fSmrg
209801e04c3fSmrg   /* Ensure that any in-progress attachment change StoreTiles finish */
209901e04c3fSmrg   if (swr_is_fence_pending(screen->flush_fence))
210001e04c3fSmrg      swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0);
210101e04c3fSmrg
210201e04c3fSmrg   /* Finally, update the in-use status of all resources involved in draw */
210301e04c3fSmrg   swr_update_resource_status(pipe, p_draw_info);
210401e04c3fSmrg
210501e04c3fSmrg   ctx->dirty = post_update_dirty_flags;
210601e04c3fSmrg}
210701e04c3fSmrg
210801e04c3fSmrg
210901e04c3fSmrgstatic struct pipe_stream_output_target *
211001e04c3fSmrgswr_create_so_target(struct pipe_context *pipe,
211101e04c3fSmrg                     struct pipe_resource *buffer,
211201e04c3fSmrg                     unsigned buffer_offset,
211301e04c3fSmrg                     unsigned buffer_size)
211401e04c3fSmrg{
211501e04c3fSmrg   struct pipe_stream_output_target *target;
211601e04c3fSmrg
211701e04c3fSmrg   target = CALLOC_STRUCT(pipe_stream_output_target);
211801e04c3fSmrg   if (!target)
211901e04c3fSmrg      return NULL;
212001e04c3fSmrg
212101e04c3fSmrg   target->context = pipe;
212201e04c3fSmrg   target->reference.count = 1;
212301e04c3fSmrg   pipe_resource_reference(&target->buffer, buffer);
212401e04c3fSmrg   target->buffer_offset = buffer_offset;
212501e04c3fSmrg   target->buffer_size = buffer_size;
212601e04c3fSmrg   return target;
212701e04c3fSmrg}
212801e04c3fSmrg
212901e04c3fSmrgstatic void
213001e04c3fSmrgswr_destroy_so_target(struct pipe_context *pipe,
213101e04c3fSmrg                      struct pipe_stream_output_target *target)
213201e04c3fSmrg{
213301e04c3fSmrg   pipe_resource_reference(&target->buffer, NULL);
213401e04c3fSmrg   FREE(target);
213501e04c3fSmrg}
213601e04c3fSmrg
213701e04c3fSmrgstatic void
213801e04c3fSmrgswr_set_so_targets(struct pipe_context *pipe,
213901e04c3fSmrg                   unsigned num_targets,
214001e04c3fSmrg                   struct pipe_stream_output_target **targets,
214101e04c3fSmrg                   const unsigned *offsets)
214201e04c3fSmrg{
214301e04c3fSmrg   struct swr_context *swr = swr_context(pipe);
214401e04c3fSmrg   uint32_t i;
214501e04c3fSmrg
214601e04c3fSmrg   assert(num_targets <= MAX_SO_STREAMS);
214701e04c3fSmrg
214801e04c3fSmrg   for (i = 0; i < num_targets; i++) {
214901e04c3fSmrg      pipe_so_target_reference(
215001e04c3fSmrg         (struct pipe_stream_output_target **)&swr->so_targets[i],
215101e04c3fSmrg         targets[i]);
215201e04c3fSmrg   }
215301e04c3fSmrg
215401e04c3fSmrg   for (/* fall-through */; i < swr->num_so_targets; i++) {
215501e04c3fSmrg      pipe_so_target_reference(
215601e04c3fSmrg         (struct pipe_stream_output_target **)&swr->so_targets[i], NULL);
215701e04c3fSmrg   }
215801e04c3fSmrg
215901e04c3fSmrg   swr->num_so_targets = num_targets;
21607ec681f3Smrg   swr->swrDC.soPrims = &swr->so_primCounter;
216101e04c3fSmrg
216201e04c3fSmrg   swr->dirty |= SWR_NEW_SO;
216301e04c3fSmrg}
216401e04c3fSmrg
21657ec681f3Smrgstatic void
21667ec681f3Smrgswr_set_patch_vertices(struct pipe_context *pipe, uint8_t patch_vertices)
21677ec681f3Smrg{
21687ec681f3Smrg   struct swr_context *swr = swr_context(pipe);
21697ec681f3Smrg
21707ec681f3Smrg   swr->patch_vertices = patch_vertices;
21717ec681f3Smrg}
21727ec681f3Smrg
217301e04c3fSmrg
217401e04c3fSmrgvoid
217501e04c3fSmrgswr_state_init(struct pipe_context *pipe)
217601e04c3fSmrg{
217701e04c3fSmrg   pipe->create_blend_state = swr_create_blend_state;
217801e04c3fSmrg   pipe->bind_blend_state = swr_bind_blend_state;
217901e04c3fSmrg   pipe->delete_blend_state = swr_delete_blend_state;
218001e04c3fSmrg
218101e04c3fSmrg   pipe->create_depth_stencil_alpha_state = swr_create_depth_stencil_state;
218201e04c3fSmrg   pipe->bind_depth_stencil_alpha_state = swr_bind_depth_stencil_state;
218301e04c3fSmrg   pipe->delete_depth_stencil_alpha_state = swr_delete_depth_stencil_state;
218401e04c3fSmrg
218501e04c3fSmrg   pipe->create_rasterizer_state = swr_create_rasterizer_state;
218601e04c3fSmrg   pipe->bind_rasterizer_state = swr_bind_rasterizer_state;
218701e04c3fSmrg   pipe->delete_rasterizer_state = swr_delete_rasterizer_state;
218801e04c3fSmrg
218901e04c3fSmrg   pipe->create_sampler_state = swr_create_sampler_state;
219001e04c3fSmrg   pipe->bind_sampler_states = swr_bind_sampler_states;
219101e04c3fSmrg   pipe->delete_sampler_state = swr_delete_sampler_state;
219201e04c3fSmrg
219301e04c3fSmrg   pipe->create_sampler_view = swr_create_sampler_view;
219401e04c3fSmrg   pipe->set_sampler_views = swr_set_sampler_views;
219501e04c3fSmrg   pipe->sampler_view_destroy = swr_sampler_view_destroy;
219601e04c3fSmrg
219701e04c3fSmrg   pipe->create_vs_state = swr_create_vs_state;
219801e04c3fSmrg   pipe->bind_vs_state = swr_bind_vs_state;
219901e04c3fSmrg   pipe->delete_vs_state = swr_delete_vs_state;
220001e04c3fSmrg
220101e04c3fSmrg   pipe->create_fs_state = swr_create_fs_state;
220201e04c3fSmrg   pipe->bind_fs_state = swr_bind_fs_state;
220301e04c3fSmrg   pipe->delete_fs_state = swr_delete_fs_state;
220401e04c3fSmrg
220501e04c3fSmrg   pipe->create_gs_state = swr_create_gs_state;
220601e04c3fSmrg   pipe->bind_gs_state = swr_bind_gs_state;
220701e04c3fSmrg   pipe->delete_gs_state = swr_delete_gs_state;
220801e04c3fSmrg
22097ec681f3Smrg   pipe->create_tcs_state = swr_create_tcs_state;
22107ec681f3Smrg   pipe->bind_tcs_state = swr_bind_tcs_state;
22117ec681f3Smrg   pipe->delete_tcs_state = swr_delete_tcs_state;
22127ec681f3Smrg
22137ec681f3Smrg   pipe->create_tes_state = swr_create_tes_state;
22147ec681f3Smrg   pipe->bind_tes_state = swr_bind_tes_state;
22157ec681f3Smrg   pipe->delete_tes_state = swr_delete_tes_state;
22167ec681f3Smrg
221701e04c3fSmrg   pipe->set_constant_buffer = swr_set_constant_buffer;
221801e04c3fSmrg
221901e04c3fSmrg   pipe->create_vertex_elements_state = swr_create_vertex_elements_state;
222001e04c3fSmrg   pipe->bind_vertex_elements_state = swr_bind_vertex_elements_state;
222101e04c3fSmrg   pipe->delete_vertex_elements_state = swr_delete_vertex_elements_state;
222201e04c3fSmrg
222301e04c3fSmrg   pipe->set_vertex_buffers = swr_set_vertex_buffers;
222401e04c3fSmrg
222501e04c3fSmrg   pipe->set_polygon_stipple = swr_set_polygon_stipple;
222601e04c3fSmrg   pipe->set_clip_state = swr_set_clip_state;
222701e04c3fSmrg   pipe->set_scissor_states = swr_set_scissor_states;
222801e04c3fSmrg   pipe->set_viewport_states = swr_set_viewport_states;
222901e04c3fSmrg
223001e04c3fSmrg   pipe->set_framebuffer_state = swr_set_framebuffer_state;
223101e04c3fSmrg
223201e04c3fSmrg   pipe->set_blend_color = swr_set_blend_color;
223301e04c3fSmrg   pipe->set_stencil_ref = swr_set_stencil_ref;
223401e04c3fSmrg
223501e04c3fSmrg   pipe->set_sample_mask = swr_set_sample_mask;
223601e04c3fSmrg   pipe->get_sample_position = swr_get_sample_position;
223701e04c3fSmrg
223801e04c3fSmrg   pipe->create_stream_output_target = swr_create_so_target;
223901e04c3fSmrg   pipe->stream_output_target_destroy = swr_destroy_so_target;
224001e04c3fSmrg   pipe->set_stream_output_targets = swr_set_so_targets;
22417ec681f3Smrg
22427ec681f3Smrg   pipe->set_patch_vertices = swr_set_patch_vertices;
224301e04c3fSmrg}
2244