1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2014-2017 Broadcom 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "util/format/u_format.h" 25bf215546Sopenharmony_ci#include "util/half_float.h" 26bf215546Sopenharmony_ci#include "v3d_context.h" 27bf215546Sopenharmony_ci#include "broadcom/common/v3d_macros.h" 28bf215546Sopenharmony_ci#include "broadcom/cle/v3dx_pack.h" 29bf215546Sopenharmony_ci#include "broadcom/common/v3d_util.h" 30bf215546Sopenharmony_ci#include "broadcom/compiler/v3d_compiler.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_cistatic uint8_t 33bf215546Sopenharmony_civ3d_factor(enum pipe_blendfactor factor, bool dst_alpha_one) 34bf215546Sopenharmony_ci{ 35bf215546Sopenharmony_ci /* We may get a bad blendfactor when blending is disabled. */ 36bf215546Sopenharmony_ci if (factor == 0) 37bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_ZERO; 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci switch (factor) { 40bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_ZERO: 41bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_ZERO; 42bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_ONE: 43bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_ONE; 44bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_COLOR: 45bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_SRC_COLOR; 46bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC_COLOR: 47bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_INV_SRC_COLOR; 48bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_DST_COLOR: 49bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_DST_COLOR; 50bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_DST_COLOR: 51bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_INV_DST_COLOR; 52bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_ALPHA: 53bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_SRC_ALPHA; 54bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 55bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_INV_SRC_ALPHA; 56bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_DST_ALPHA: 57bf215546Sopenharmony_ci return (dst_alpha_one ? 58bf215546Sopenharmony_ci V3D_BLEND_FACTOR_ONE : 59bf215546Sopenharmony_ci V3D_BLEND_FACTOR_DST_ALPHA); 60bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_DST_ALPHA: 61bf215546Sopenharmony_ci return (dst_alpha_one ? 62bf215546Sopenharmony_ci V3D_BLEND_FACTOR_ZERO : 63bf215546Sopenharmony_ci V3D_BLEND_FACTOR_INV_DST_ALPHA); 64bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_COLOR: 65bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_CONST_COLOR; 66bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_COLOR: 67bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_INV_CONST_COLOR; 68bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_ALPHA: 69bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_CONST_ALPHA; 70bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 71bf215546Sopenharmony_ci return V3D_BLEND_FACTOR_INV_CONST_ALPHA; 72bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 73bf215546Sopenharmony_ci return (dst_alpha_one ? 74bf215546Sopenharmony_ci V3D_BLEND_FACTOR_ZERO : 75bf215546Sopenharmony_ci V3D_BLEND_FACTOR_SRC_ALPHA_SATURATE); 76bf215546Sopenharmony_ci default: 77bf215546Sopenharmony_ci unreachable("Bad blend factor"); 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci#if V3D_VERSION < 40 82bf215546Sopenharmony_cistatic inline uint16_t 83bf215546Sopenharmony_ciswizzled_border_color(const struct v3d_device_info *devinfo, 84bf215546Sopenharmony_ci struct pipe_sampler_state *sampler, 85bf215546Sopenharmony_ci struct v3d_sampler_view *sview, 86bf215546Sopenharmony_ci int chan) 87bf215546Sopenharmony_ci{ 88bf215546Sopenharmony_ci const struct util_format_description *desc = 89bf215546Sopenharmony_ci util_format_description(sview->base.format); 90bf215546Sopenharmony_ci uint8_t swiz = chan; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci /* If we're doing swizzling in the sampler, then only rearrange the 93bf215546Sopenharmony_ci * border color for the mismatch between the V3D texture format and 94bf215546Sopenharmony_ci * the PIPE_FORMAT, since GL_ARB_texture_swizzle will be handled by 95bf215546Sopenharmony_ci * the sampler's swizzle. 96bf215546Sopenharmony_ci * 97bf215546Sopenharmony_ci * For swizzling in the shader, we don't do any pre-swizzling of the 98bf215546Sopenharmony_ci * border color. 99bf215546Sopenharmony_ci */ 100bf215546Sopenharmony_ci if (v3d_get_tex_return_size(devinfo, sview->base.format, 101bf215546Sopenharmony_ci sampler->compare_mode) != 32) 102bf215546Sopenharmony_ci swiz = desc->swizzle[swiz]; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci switch (swiz) { 105bf215546Sopenharmony_ci case PIPE_SWIZZLE_0: 106bf215546Sopenharmony_ci return _mesa_float_to_half(0.0); 107bf215546Sopenharmony_ci case PIPE_SWIZZLE_1: 108bf215546Sopenharmony_ci return _mesa_float_to_half(1.0); 109bf215546Sopenharmony_ci default: 110bf215546Sopenharmony_ci return _mesa_float_to_half(sampler->border_color.f[swiz]); 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_cistatic void 115bf215546Sopenharmony_ciemit_one_texture(struct v3d_context *v3d, struct v3d_texture_stateobj *stage_tex, 116bf215546Sopenharmony_ci int i) 117bf215546Sopenharmony_ci{ 118bf215546Sopenharmony_ci struct v3d_job *job = v3d->job; 119bf215546Sopenharmony_ci struct pipe_sampler_state *psampler = stage_tex->samplers[i]; 120bf215546Sopenharmony_ci struct v3d_sampler_state *sampler = v3d_sampler_state(psampler); 121bf215546Sopenharmony_ci struct pipe_sampler_view *psview = stage_tex->textures[i]; 122bf215546Sopenharmony_ci struct v3d_sampler_view *sview = v3d_sampler_view(psview); 123bf215546Sopenharmony_ci struct pipe_resource *prsc = psview->texture; 124bf215546Sopenharmony_ci struct v3d_resource *rsc = v3d_resource(prsc); 125bf215546Sopenharmony_ci const struct v3d_device_info *devinfo = &v3d->screen->devinfo; 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci stage_tex->texture_state[i].offset = 128bf215546Sopenharmony_ci v3d_cl_ensure_space(&job->indirect, 129bf215546Sopenharmony_ci cl_packet_length(TEXTURE_SHADER_STATE), 130bf215546Sopenharmony_ci 32); 131bf215546Sopenharmony_ci v3d_bo_set_reference(&stage_tex->texture_state[i].bo, 132bf215546Sopenharmony_ci job->indirect.bo); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci uint32_t return_size = v3d_get_tex_return_size(devinfo, psview->format, 135bf215546Sopenharmony_ci psampler->compare_mode); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci struct V3D33_TEXTURE_SHADER_STATE unpacked = { 138bf215546Sopenharmony_ci /* XXX */ 139bf215546Sopenharmony_ci .border_color_red = swizzled_border_color(devinfo, psampler, 140bf215546Sopenharmony_ci sview, 0), 141bf215546Sopenharmony_ci .border_color_green = swizzled_border_color(devinfo, psampler, 142bf215546Sopenharmony_ci sview, 1), 143bf215546Sopenharmony_ci .border_color_blue = swizzled_border_color(devinfo, psampler, 144bf215546Sopenharmony_ci sview, 2), 145bf215546Sopenharmony_ci .border_color_alpha = swizzled_border_color(devinfo, psampler, 146bf215546Sopenharmony_ci sview, 3), 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci /* In the normal texturing path, the LOD gets clamped between 149bf215546Sopenharmony_ci * min/max, and the base_level field (set in the sampler view 150bf215546Sopenharmony_ci * from first_level) only decides where the min/mag switch 151bf215546Sopenharmony_ci * happens, so we need to use the LOD clamps to keep us 152bf215546Sopenharmony_ci * between min and max. 153bf215546Sopenharmony_ci * 154bf215546Sopenharmony_ci * For txf, the LOD clamp is still used, despite GL not 155bf215546Sopenharmony_ci * wanting that. We will need to have a separate 156bf215546Sopenharmony_ci * TEXTURE_SHADER_STATE that ignores psview->min/max_lod to 157bf215546Sopenharmony_ci * support txf properly. 158bf215546Sopenharmony_ci */ 159bf215546Sopenharmony_ci .min_level_of_detail = MIN2(psview->u.tex.first_level + 160bf215546Sopenharmony_ci MAX2(psampler->min_lod, 0), 161bf215546Sopenharmony_ci psview->u.tex.last_level), 162bf215546Sopenharmony_ci .max_level_of_detail = MIN2(psview->u.tex.first_level + 163bf215546Sopenharmony_ci MAX2(psampler->max_lod, 164bf215546Sopenharmony_ci psampler->min_lod), 165bf215546Sopenharmony_ci psview->u.tex.last_level), 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci .texture_base_pointer = cl_address(rsc->bo, 168bf215546Sopenharmony_ci rsc->slices[0].offset), 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci .output_32_bit = return_size == 32, 171bf215546Sopenharmony_ci }; 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci /* Set up the sampler swizzle if we're doing 16-bit sampling. For 174bf215546Sopenharmony_ci * 32-bit, we leave swizzling up to the shader compiler. 175bf215546Sopenharmony_ci * 176bf215546Sopenharmony_ci * Note: Contrary to the docs, the swizzle still applies even if the 177bf215546Sopenharmony_ci * return size is 32. It's just that you probably want to swizzle in 178bf215546Sopenharmony_ci * the shader, because you need the Y/Z/W channels to be defined. 179bf215546Sopenharmony_ci */ 180bf215546Sopenharmony_ci if (return_size == 32) { 181bf215546Sopenharmony_ci unpacked.swizzle_r = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_X); 182bf215546Sopenharmony_ci unpacked.swizzle_g = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_Y); 183bf215546Sopenharmony_ci unpacked.swizzle_b = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_Z); 184bf215546Sopenharmony_ci unpacked.swizzle_a = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_W); 185bf215546Sopenharmony_ci } else { 186bf215546Sopenharmony_ci unpacked.swizzle_r = v3d_translate_pipe_swizzle(sview->swizzle[0]); 187bf215546Sopenharmony_ci unpacked.swizzle_g = v3d_translate_pipe_swizzle(sview->swizzle[1]); 188bf215546Sopenharmony_ci unpacked.swizzle_b = v3d_translate_pipe_swizzle(sview->swizzle[2]); 189bf215546Sopenharmony_ci unpacked.swizzle_a = v3d_translate_pipe_swizzle(sview->swizzle[3]); 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci int min_img_filter = psampler->min_img_filter; 193bf215546Sopenharmony_ci int min_mip_filter = psampler->min_mip_filter; 194bf215546Sopenharmony_ci int mag_img_filter = psampler->mag_img_filter; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci if (return_size == 32) { 197bf215546Sopenharmony_ci min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 198bf215546Sopenharmony_ci min_img_filter = PIPE_TEX_FILTER_NEAREST; 199bf215546Sopenharmony_ci mag_img_filter = PIPE_TEX_FILTER_NEAREST; 200bf215546Sopenharmony_ci } 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci bool min_nearest = min_img_filter == PIPE_TEX_FILTER_NEAREST; 203bf215546Sopenharmony_ci switch (min_mip_filter) { 204bf215546Sopenharmony_ci case PIPE_TEX_MIPFILTER_NONE: 205bf215546Sopenharmony_ci unpacked.filter += min_nearest ? 2 : 0; 206bf215546Sopenharmony_ci break; 207bf215546Sopenharmony_ci case PIPE_TEX_MIPFILTER_NEAREST: 208bf215546Sopenharmony_ci unpacked.filter += min_nearest ? 4 : 8; 209bf215546Sopenharmony_ci break; 210bf215546Sopenharmony_ci case PIPE_TEX_MIPFILTER_LINEAR: 211bf215546Sopenharmony_ci unpacked.filter += min_nearest ? 4 : 8; 212bf215546Sopenharmony_ci unpacked.filter += 2; 213bf215546Sopenharmony_ci break; 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci if (mag_img_filter == PIPE_TEX_FILTER_NEAREST) 217bf215546Sopenharmony_ci unpacked.filter++; 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci if (psampler->max_anisotropy > 8) 220bf215546Sopenharmony_ci unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_16_1; 221bf215546Sopenharmony_ci else if (psampler->max_anisotropy > 4) 222bf215546Sopenharmony_ci unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_8_1; 223bf215546Sopenharmony_ci else if (psampler->max_anisotropy > 2) 224bf215546Sopenharmony_ci unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_4_1; 225bf215546Sopenharmony_ci else if (psampler->max_anisotropy) 226bf215546Sopenharmony_ci unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_2_1; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci uint8_t packed[cl_packet_length(TEXTURE_SHADER_STATE)]; 229bf215546Sopenharmony_ci cl_packet_pack(TEXTURE_SHADER_STATE)(&job->indirect, packed, &unpacked); 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(packed); i++) 232bf215546Sopenharmony_ci packed[i] |= sview->texture_shader_state[i] | sampler->texture_shader_state[i]; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci /* TMU indirect structs need to be 32b aligned. */ 235bf215546Sopenharmony_ci v3d_cl_ensure_space(&job->indirect, ARRAY_SIZE(packed), 32); 236bf215546Sopenharmony_ci cl_emit_prepacked(&job->indirect, &packed); 237bf215546Sopenharmony_ci} 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_cistatic void 240bf215546Sopenharmony_ciemit_textures(struct v3d_context *v3d, struct v3d_texture_stateobj *stage_tex) 241bf215546Sopenharmony_ci{ 242bf215546Sopenharmony_ci for (int i = 0; i < stage_tex->num_textures; i++) { 243bf215546Sopenharmony_ci if (stage_tex->textures[i]) 244bf215546Sopenharmony_ci emit_one_texture(v3d, stage_tex, i); 245bf215546Sopenharmony_ci } 246bf215546Sopenharmony_ci} 247bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */ 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_cistatic uint32_t 250bf215546Sopenharmony_citranslate_colormask(struct v3d_context *v3d, uint32_t colormask, int rt) 251bf215546Sopenharmony_ci{ 252bf215546Sopenharmony_ci if (v3d->swap_color_rb & (1 << rt)) { 253bf215546Sopenharmony_ci colormask = ((colormask & (2 | 8)) | 254bf215546Sopenharmony_ci ((colormask & 1) << 2) | 255bf215546Sopenharmony_ci ((colormask & 4) >> 2)); 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci return (~colormask) & 0xf; 259bf215546Sopenharmony_ci} 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_cistatic void 262bf215546Sopenharmony_ciemit_rt_blend(struct v3d_context *v3d, struct v3d_job *job, 263bf215546Sopenharmony_ci struct pipe_blend_state *blend, int rt, uint8_t rt_mask, 264bf215546Sopenharmony_ci bool blend_dst_alpha_one) 265bf215546Sopenharmony_ci{ 266bf215546Sopenharmony_ci struct pipe_rt_blend_state *rtblend = &blend->rt[rt]; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci#if V3D_VERSION >= 40 269bf215546Sopenharmony_ci /* We don't need to emit blend state for disabled RTs. */ 270bf215546Sopenharmony_ci if (!rtblend->blend_enable) 271bf215546Sopenharmony_ci return; 272bf215546Sopenharmony_ci#endif 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci cl_emit(&job->bcl, BLEND_CFG, config) { 275bf215546Sopenharmony_ci#if V3D_VERSION >= 40 276bf215546Sopenharmony_ci config.render_target_mask = rt_mask; 277bf215546Sopenharmony_ci#else 278bf215546Sopenharmony_ci assert(rt == 0); 279bf215546Sopenharmony_ci#endif 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci config.color_blend_mode = rtblend->rgb_func; 282bf215546Sopenharmony_ci config.color_blend_dst_factor = 283bf215546Sopenharmony_ci v3d_factor(rtblend->rgb_dst_factor, 284bf215546Sopenharmony_ci blend_dst_alpha_one); 285bf215546Sopenharmony_ci config.color_blend_src_factor = 286bf215546Sopenharmony_ci v3d_factor(rtblend->rgb_src_factor, 287bf215546Sopenharmony_ci blend_dst_alpha_one); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci config.alpha_blend_mode = rtblend->alpha_func; 290bf215546Sopenharmony_ci config.alpha_blend_dst_factor = 291bf215546Sopenharmony_ci v3d_factor(rtblend->alpha_dst_factor, 292bf215546Sopenharmony_ci blend_dst_alpha_one); 293bf215546Sopenharmony_ci config.alpha_blend_src_factor = 294bf215546Sopenharmony_ci v3d_factor(rtblend->alpha_src_factor, 295bf215546Sopenharmony_ci blend_dst_alpha_one); 296bf215546Sopenharmony_ci } 297bf215546Sopenharmony_ci} 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_cistatic void 300bf215546Sopenharmony_ciemit_flat_shade_flags(struct v3d_job *job, 301bf215546Sopenharmony_ci int varying_offset, 302bf215546Sopenharmony_ci uint32_t varyings, 303bf215546Sopenharmony_ci enum V3DX(Varying_Flags_Action) lower, 304bf215546Sopenharmony_ci enum V3DX(Varying_Flags_Action) higher) 305bf215546Sopenharmony_ci{ 306bf215546Sopenharmony_ci cl_emit(&job->bcl, FLAT_SHADE_FLAGS, flags) { 307bf215546Sopenharmony_ci flags.varying_offset_v0 = varying_offset; 308bf215546Sopenharmony_ci flags.flat_shade_flags_for_varyings_v024 = varyings; 309bf215546Sopenharmony_ci flags.action_for_flat_shade_flags_of_lower_numbered_varyings = 310bf215546Sopenharmony_ci lower; 311bf215546Sopenharmony_ci flags.action_for_flat_shade_flags_of_higher_numbered_varyings = 312bf215546Sopenharmony_ci higher; 313bf215546Sopenharmony_ci } 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci#if V3D_VERSION >= 40 317bf215546Sopenharmony_cistatic void 318bf215546Sopenharmony_ciemit_noperspective_flags(struct v3d_job *job, 319bf215546Sopenharmony_ci int varying_offset, 320bf215546Sopenharmony_ci uint32_t varyings, 321bf215546Sopenharmony_ci enum V3DX(Varying_Flags_Action) lower, 322bf215546Sopenharmony_ci enum V3DX(Varying_Flags_Action) higher) 323bf215546Sopenharmony_ci{ 324bf215546Sopenharmony_ci cl_emit(&job->bcl, NON_PERSPECTIVE_FLAGS, flags) { 325bf215546Sopenharmony_ci flags.varying_offset_v0 = varying_offset; 326bf215546Sopenharmony_ci flags.non_perspective_flags_for_varyings_v024 = varyings; 327bf215546Sopenharmony_ci flags.action_for_non_perspective_flags_of_lower_numbered_varyings = 328bf215546Sopenharmony_ci lower; 329bf215546Sopenharmony_ci flags.action_for_non_perspective_flags_of_higher_numbered_varyings = 330bf215546Sopenharmony_ci higher; 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci} 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_cistatic void 335bf215546Sopenharmony_ciemit_centroid_flags(struct v3d_job *job, 336bf215546Sopenharmony_ci int varying_offset, 337bf215546Sopenharmony_ci uint32_t varyings, 338bf215546Sopenharmony_ci enum V3DX(Varying_Flags_Action) lower, 339bf215546Sopenharmony_ci enum V3DX(Varying_Flags_Action) higher) 340bf215546Sopenharmony_ci{ 341bf215546Sopenharmony_ci cl_emit(&job->bcl, CENTROID_FLAGS, flags) { 342bf215546Sopenharmony_ci flags.varying_offset_v0 = varying_offset; 343bf215546Sopenharmony_ci flags.centroid_flags_for_varyings_v024 = varyings; 344bf215546Sopenharmony_ci flags.action_for_centroid_flags_of_lower_numbered_varyings = 345bf215546Sopenharmony_ci lower; 346bf215546Sopenharmony_ci flags.action_for_centroid_flags_of_higher_numbered_varyings = 347bf215546Sopenharmony_ci higher; 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci} 350bf215546Sopenharmony_ci#endif /* V3D_VERSION >= 40 */ 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_cistatic bool 353bf215546Sopenharmony_ciemit_varying_flags(struct v3d_job *job, uint32_t *flags, 354bf215546Sopenharmony_ci void (*flag_emit_callback)(struct v3d_job *job, 355bf215546Sopenharmony_ci int varying_offset, 356bf215546Sopenharmony_ci uint32_t flags, 357bf215546Sopenharmony_ci enum V3DX(Varying_Flags_Action) lower, 358bf215546Sopenharmony_ci enum V3DX(Varying_Flags_Action) higher)) 359bf215546Sopenharmony_ci{ 360bf215546Sopenharmony_ci struct v3d_context *v3d = job->v3d; 361bf215546Sopenharmony_ci bool emitted_any = false; 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(v3d->prog.fs->prog_data.fs->flat_shade_flags); i++) { 364bf215546Sopenharmony_ci if (!flags[i]) 365bf215546Sopenharmony_ci continue; 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci if (emitted_any) { 368bf215546Sopenharmony_ci flag_emit_callback(job, i, flags[i], 369bf215546Sopenharmony_ci V3D_VARYING_FLAGS_ACTION_UNCHANGED, 370bf215546Sopenharmony_ci V3D_VARYING_FLAGS_ACTION_UNCHANGED); 371bf215546Sopenharmony_ci } else if (i == 0) { 372bf215546Sopenharmony_ci flag_emit_callback(job, i, flags[i], 373bf215546Sopenharmony_ci V3D_VARYING_FLAGS_ACTION_UNCHANGED, 374bf215546Sopenharmony_ci V3D_VARYING_FLAGS_ACTION_ZEROED); 375bf215546Sopenharmony_ci } else { 376bf215546Sopenharmony_ci flag_emit_callback(job, i, flags[i], 377bf215546Sopenharmony_ci V3D_VARYING_FLAGS_ACTION_ZEROED, 378bf215546Sopenharmony_ci V3D_VARYING_FLAGS_ACTION_ZEROED); 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci emitted_any = true; 381bf215546Sopenharmony_ci } 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci return emitted_any; 384bf215546Sopenharmony_ci} 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_cistatic inline struct v3d_uncompiled_shader * 387bf215546Sopenharmony_ciget_tf_shader(struct v3d_context *v3d) 388bf215546Sopenharmony_ci{ 389bf215546Sopenharmony_ci if (v3d->prog.bind_gs) 390bf215546Sopenharmony_ci return v3d->prog.bind_gs; 391bf215546Sopenharmony_ci else 392bf215546Sopenharmony_ci return v3d->prog.bind_vs; 393bf215546Sopenharmony_ci} 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_civoid 396bf215546Sopenharmony_civ3dX(emit_state)(struct pipe_context *pctx) 397bf215546Sopenharmony_ci{ 398bf215546Sopenharmony_ci struct v3d_context *v3d = v3d_context(pctx); 399bf215546Sopenharmony_ci struct v3d_job *job = v3d->job; 400bf215546Sopenharmony_ci bool rasterizer_discard = v3d->rasterizer->base.rasterizer_discard; 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci if (v3d->dirty & (V3D_DIRTY_SCISSOR | V3D_DIRTY_VIEWPORT | 403bf215546Sopenharmony_ci V3D_DIRTY_RASTERIZER)) { 404bf215546Sopenharmony_ci float *vpscale = v3d->viewport.scale; 405bf215546Sopenharmony_ci float *vptranslate = v3d->viewport.translate; 406bf215546Sopenharmony_ci float vp_minx = -fabsf(vpscale[0]) + vptranslate[0]; 407bf215546Sopenharmony_ci float vp_maxx = fabsf(vpscale[0]) + vptranslate[0]; 408bf215546Sopenharmony_ci float vp_miny = -fabsf(vpscale[1]) + vptranslate[1]; 409bf215546Sopenharmony_ci float vp_maxy = fabsf(vpscale[1]) + vptranslate[1]; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci /* Clip to the scissor if it's enabled, but still clip to the 412bf215546Sopenharmony_ci * drawable regardless since that controls where the binner 413bf215546Sopenharmony_ci * tries to put things. 414bf215546Sopenharmony_ci * 415bf215546Sopenharmony_ci * Additionally, always clip the rendering to the viewport, 416bf215546Sopenharmony_ci * since the hardware does guardband clipping, meaning 417bf215546Sopenharmony_ci * primitives would rasterize outside of the view volume. 418bf215546Sopenharmony_ci */ 419bf215546Sopenharmony_ci uint32_t minx, miny, maxx, maxy; 420bf215546Sopenharmony_ci if (!v3d->rasterizer->base.scissor) { 421bf215546Sopenharmony_ci minx = MAX2(vp_minx, 0); 422bf215546Sopenharmony_ci miny = MAX2(vp_miny, 0); 423bf215546Sopenharmony_ci maxx = MIN2(vp_maxx, job->draw_width); 424bf215546Sopenharmony_ci maxy = MIN2(vp_maxy, job->draw_height); 425bf215546Sopenharmony_ci } else { 426bf215546Sopenharmony_ci minx = MAX2(vp_minx, v3d->scissor.minx); 427bf215546Sopenharmony_ci miny = MAX2(vp_miny, v3d->scissor.miny); 428bf215546Sopenharmony_ci maxx = MIN2(vp_maxx, v3d->scissor.maxx); 429bf215546Sopenharmony_ci maxy = MIN2(vp_maxy, v3d->scissor.maxy); 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci cl_emit(&job->bcl, CLIP_WINDOW, clip) { 433bf215546Sopenharmony_ci clip.clip_window_left_pixel_coordinate = minx; 434bf215546Sopenharmony_ci clip.clip_window_bottom_pixel_coordinate = miny; 435bf215546Sopenharmony_ci if (maxx > minx && maxy > miny) { 436bf215546Sopenharmony_ci clip.clip_window_width_in_pixels = maxx - minx; 437bf215546Sopenharmony_ci clip.clip_window_height_in_pixels = maxy - miny; 438bf215546Sopenharmony_ci } else if (V3D_VERSION < 41) { 439bf215546Sopenharmony_ci /* The HW won't entirely clip out when scissor 440bf215546Sopenharmony_ci * w/h is 0. Just treat it the same as 441bf215546Sopenharmony_ci * rasterizer discard. 442bf215546Sopenharmony_ci */ 443bf215546Sopenharmony_ci rasterizer_discard = true; 444bf215546Sopenharmony_ci clip.clip_window_width_in_pixels = 1; 445bf215546Sopenharmony_ci clip.clip_window_height_in_pixels = 1; 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci } 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci job->draw_min_x = MIN2(job->draw_min_x, minx); 450bf215546Sopenharmony_ci job->draw_min_y = MIN2(job->draw_min_y, miny); 451bf215546Sopenharmony_ci job->draw_max_x = MAX2(job->draw_max_x, maxx); 452bf215546Sopenharmony_ci job->draw_max_y = MAX2(job->draw_max_y, maxy); 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci if (!v3d->rasterizer->base.scissor) { 455bf215546Sopenharmony_ci job->scissor.disabled = true; 456bf215546Sopenharmony_ci } else if (!job->scissor.disabled && 457bf215546Sopenharmony_ci (v3d->dirty & V3D_DIRTY_SCISSOR)) { 458bf215546Sopenharmony_ci if (job->scissor.count < MAX_JOB_SCISSORS) { 459bf215546Sopenharmony_ci job->scissor.rects[job->scissor.count].min_x = 460bf215546Sopenharmony_ci v3d->scissor.minx; 461bf215546Sopenharmony_ci job->scissor.rects[job->scissor.count].min_y = 462bf215546Sopenharmony_ci v3d->scissor.miny; 463bf215546Sopenharmony_ci job->scissor.rects[job->scissor.count].max_x = 464bf215546Sopenharmony_ci v3d->scissor.maxx - 1; 465bf215546Sopenharmony_ci job->scissor.rects[job->scissor.count].max_y = 466bf215546Sopenharmony_ci v3d->scissor.maxy - 1; 467bf215546Sopenharmony_ci job->scissor.count++; 468bf215546Sopenharmony_ci } else { 469bf215546Sopenharmony_ci job->scissor.disabled = true; 470bf215546Sopenharmony_ci perf_debug("Too many scissor rects."); 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci } 473bf215546Sopenharmony_ci } 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci if (v3d->dirty & (V3D_DIRTY_RASTERIZER | 476bf215546Sopenharmony_ci V3D_DIRTY_ZSA | 477bf215546Sopenharmony_ci V3D_DIRTY_BLEND | 478bf215546Sopenharmony_ci V3D_DIRTY_COMPILED_FS)) { 479bf215546Sopenharmony_ci cl_emit(&job->bcl, CFG_BITS, config) { 480bf215546Sopenharmony_ci config.enable_forward_facing_primitive = 481bf215546Sopenharmony_ci !rasterizer_discard && 482bf215546Sopenharmony_ci !(v3d->rasterizer->base.cull_face & 483bf215546Sopenharmony_ci PIPE_FACE_FRONT); 484bf215546Sopenharmony_ci config.enable_reverse_facing_primitive = 485bf215546Sopenharmony_ci !rasterizer_discard && 486bf215546Sopenharmony_ci !(v3d->rasterizer->base.cull_face & 487bf215546Sopenharmony_ci PIPE_FACE_BACK); 488bf215546Sopenharmony_ci /* This seems backwards, but it's what gets the 489bf215546Sopenharmony_ci * clipflat test to pass. 490bf215546Sopenharmony_ci */ 491bf215546Sopenharmony_ci config.clockwise_primitives = 492bf215546Sopenharmony_ci v3d->rasterizer->base.front_ccw; 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci config.enable_depth_offset = 495bf215546Sopenharmony_ci v3d->rasterizer->base.offset_tri; 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci /* V3D follows GL behavior where the sample mask only 498bf215546Sopenharmony_ci * applies when MSAA is enabled. Gallium has sample 499bf215546Sopenharmony_ci * mask apply anyway, and the MSAA blit shaders will 500bf215546Sopenharmony_ci * set sample mask without explicitly setting 501bf215546Sopenharmony_ci * rasterizer oversample. Just force it on here, 502bf215546Sopenharmony_ci * since the blit shaders are the only way to have 503bf215546Sopenharmony_ci * !multisample && samplemask != 0xf. 504bf215546Sopenharmony_ci */ 505bf215546Sopenharmony_ci config.rasterizer_oversample_mode = 506bf215546Sopenharmony_ci v3d->rasterizer->base.multisample || 507bf215546Sopenharmony_ci v3d->sample_mask != 0xf; 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci config.direct3d_provoking_vertex = 510bf215546Sopenharmony_ci v3d->rasterizer->base.flatshade_first; 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ci config.blend_enable = v3d->blend->blend_enables; 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci /* Note: EZ state may update based on the compiled FS, 515bf215546Sopenharmony_ci * along with ZSA 516bf215546Sopenharmony_ci */ 517bf215546Sopenharmony_ci config.early_z_updates_enable = 518bf215546Sopenharmony_ci (job->ez_state != V3D_EZ_DISABLED); 519bf215546Sopenharmony_ci if (v3d->zsa->base.depth_enabled) { 520bf215546Sopenharmony_ci config.z_updates_enable = 521bf215546Sopenharmony_ci v3d->zsa->base.depth_writemask; 522bf215546Sopenharmony_ci config.early_z_enable = 523bf215546Sopenharmony_ci config.early_z_updates_enable; 524bf215546Sopenharmony_ci config.depth_test_function = 525bf215546Sopenharmony_ci v3d->zsa->base.depth_func; 526bf215546Sopenharmony_ci } else { 527bf215546Sopenharmony_ci config.depth_test_function = PIPE_FUNC_ALWAYS; 528bf215546Sopenharmony_ci } 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci config.stencil_enable = 531bf215546Sopenharmony_ci v3d->zsa->base.stencil[0].enabled; 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci /* Use nicer line caps when line smoothing is 534bf215546Sopenharmony_ci * enabled 535bf215546Sopenharmony_ci */ 536bf215546Sopenharmony_ci config.line_rasterization = 537bf215546Sopenharmony_ci v3d_line_smoothing_enabled(v3d) ? 538bf215546Sopenharmony_ci V3D_LINE_RASTERIZATION_PERP_END_CAPS : 539bf215546Sopenharmony_ci V3D_LINE_RASTERIZATION_DIAMOND_EXIT; 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci } 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_RASTERIZER && 545bf215546Sopenharmony_ci v3d->rasterizer->base.offset_tri) { 546bf215546Sopenharmony_ci if (job->zsbuf && 547bf215546Sopenharmony_ci job->zsbuf->format == PIPE_FORMAT_Z16_UNORM) { 548bf215546Sopenharmony_ci cl_emit_prepacked_sized(&job->bcl, 549bf215546Sopenharmony_ci v3d->rasterizer->depth_offset_z16, 550bf215546Sopenharmony_ci cl_packet_length(DEPTH_OFFSET)); 551bf215546Sopenharmony_ci } else { 552bf215546Sopenharmony_ci cl_emit_prepacked_sized(&job->bcl, 553bf215546Sopenharmony_ci v3d->rasterizer->depth_offset, 554bf215546Sopenharmony_ci cl_packet_length(DEPTH_OFFSET)); 555bf215546Sopenharmony_ci } 556bf215546Sopenharmony_ci } 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_RASTERIZER) { 559bf215546Sopenharmony_ci cl_emit(&job->bcl, POINT_SIZE, point_size) { 560bf215546Sopenharmony_ci point_size.point_size = v3d->rasterizer->point_size; 561bf215546Sopenharmony_ci } 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci cl_emit(&job->bcl, LINE_WIDTH, line_width) { 564bf215546Sopenharmony_ci line_width.line_width = v3d_get_real_line_width(v3d); 565bf215546Sopenharmony_ci } 566bf215546Sopenharmony_ci } 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_VIEWPORT) { 569bf215546Sopenharmony_ci cl_emit(&job->bcl, CLIPPER_XY_SCALING, clip) { 570bf215546Sopenharmony_ci clip.viewport_half_width_in_1_256th_of_pixel = 571bf215546Sopenharmony_ci v3d->viewport.scale[0] * 256.0f; 572bf215546Sopenharmony_ci clip.viewport_half_height_in_1_256th_of_pixel = 573bf215546Sopenharmony_ci v3d->viewport.scale[1] * 256.0f; 574bf215546Sopenharmony_ci } 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci cl_emit(&job->bcl, CLIPPER_Z_SCALE_AND_OFFSET, clip) { 577bf215546Sopenharmony_ci clip.viewport_z_offset_zc_to_zs = 578bf215546Sopenharmony_ci v3d->viewport.translate[2]; 579bf215546Sopenharmony_ci clip.viewport_z_scale_zc_to_zs = 580bf215546Sopenharmony_ci v3d->viewport.scale[2]; 581bf215546Sopenharmony_ci } 582bf215546Sopenharmony_ci cl_emit(&job->bcl, CLIPPER_Z_MIN_MAX_CLIPPING_PLANES, clip) { 583bf215546Sopenharmony_ci float z1 = (v3d->viewport.translate[2] - 584bf215546Sopenharmony_ci v3d->viewport.scale[2]); 585bf215546Sopenharmony_ci float z2 = (v3d->viewport.translate[2] + 586bf215546Sopenharmony_ci v3d->viewport.scale[2]); 587bf215546Sopenharmony_ci clip.minimum_zw = MIN2(z1, z2); 588bf215546Sopenharmony_ci clip.maximum_zw = MAX2(z1, z2); 589bf215546Sopenharmony_ci } 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci cl_emit(&job->bcl, VIEWPORT_OFFSET, vp) { 592bf215546Sopenharmony_ci vp.viewport_centre_x_coordinate = 593bf215546Sopenharmony_ci v3d->viewport.translate[0]; 594bf215546Sopenharmony_ci vp.viewport_centre_y_coordinate = 595bf215546Sopenharmony_ci v3d->viewport.translate[1]; 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci } 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_BLEND) { 600bf215546Sopenharmony_ci struct v3d_blend_state *blend = v3d->blend; 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci if (blend->blend_enables) { 603bf215546Sopenharmony_ci#if V3D_VERSION >= 40 604bf215546Sopenharmony_ci cl_emit(&job->bcl, BLEND_ENABLES, enables) { 605bf215546Sopenharmony_ci enables.mask = blend->blend_enables; 606bf215546Sopenharmony_ci } 607bf215546Sopenharmony_ci#endif 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci if (blend->base.independent_blend_enable) { 610bf215546Sopenharmony_ci for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) 611bf215546Sopenharmony_ci emit_rt_blend(v3d, job, &blend->base, i, 612bf215546Sopenharmony_ci (1 << i), 613bf215546Sopenharmony_ci v3d->blend_dst_alpha_one & (1 << i)); 614bf215546Sopenharmony_ci } else if (v3d->blend_dst_alpha_one && 615bf215546Sopenharmony_ci util_bitcount(v3d->blend_dst_alpha_one) < job->nr_cbufs) { 616bf215546Sopenharmony_ci /* Even if we don't have independent per-RT 617bf215546Sopenharmony_ci * blending, we may have a combination of RT 618bf215546Sopenharmony_ci * formats were some RTs have an alpha channel 619bf215546Sopenharmony_ci * and others don't. Since this affects how 620bf215546Sopenharmony_ci * blending is performed, we also need to emit 621bf215546Sopenharmony_ci * independent blend configurations in this 622bf215546Sopenharmony_ci * case: one for RTs with alpha and one for 623bf215546Sopenharmony_ci * RTs without. 624bf215546Sopenharmony_ci */ 625bf215546Sopenharmony_ci emit_rt_blend(v3d, job, &blend->base, 0, 626bf215546Sopenharmony_ci ((1 << V3D_MAX_DRAW_BUFFERS) - 1) & 627bf215546Sopenharmony_ci v3d->blend_dst_alpha_one, 628bf215546Sopenharmony_ci true); 629bf215546Sopenharmony_ci emit_rt_blend(v3d, job, &blend->base, 0, 630bf215546Sopenharmony_ci ((1 << V3D_MAX_DRAW_BUFFERS) - 1) & 631bf215546Sopenharmony_ci ~v3d->blend_dst_alpha_one, 632bf215546Sopenharmony_ci false); 633bf215546Sopenharmony_ci } else { 634bf215546Sopenharmony_ci emit_rt_blend(v3d, job, &blend->base, 0, 635bf215546Sopenharmony_ci (1 << V3D_MAX_DRAW_BUFFERS) - 1, 636bf215546Sopenharmony_ci v3d->blend_dst_alpha_one); 637bf215546Sopenharmony_ci } 638bf215546Sopenharmony_ci } 639bf215546Sopenharmony_ci } 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_BLEND) { 642bf215546Sopenharmony_ci struct pipe_blend_state *blend = &v3d->blend->base; 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_ci cl_emit(&job->bcl, COLOR_WRITE_MASKS, mask) { 645bf215546Sopenharmony_ci for (int i = 0; i < 4; i++) { 646bf215546Sopenharmony_ci int rt = blend->independent_blend_enable ? i : 0; 647bf215546Sopenharmony_ci int rt_mask = blend->rt[rt].colormask; 648bf215546Sopenharmony_ci 649bf215546Sopenharmony_ci mask.mask |= translate_colormask(v3d, rt_mask, 650bf215546Sopenharmony_ci i) << (4 * i); 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci } 653bf215546Sopenharmony_ci } 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_ci /* GFXH-1431: On V3D 3.x, writing BLEND_CONFIG resets the constant 656bf215546Sopenharmony_ci * color. 657bf215546Sopenharmony_ci */ 658bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_BLEND_COLOR || 659bf215546Sopenharmony_ci (V3D_VERSION < 41 && (v3d->dirty & V3D_DIRTY_BLEND))) { 660bf215546Sopenharmony_ci cl_emit(&job->bcl, BLEND_CONSTANT_COLOR, color) { 661bf215546Sopenharmony_ci color.red_f16 = (v3d->swap_color_rb ? 662bf215546Sopenharmony_ci v3d->blend_color.hf[2] : 663bf215546Sopenharmony_ci v3d->blend_color.hf[0]); 664bf215546Sopenharmony_ci color.green_f16 = v3d->blend_color.hf[1]; 665bf215546Sopenharmony_ci color.blue_f16 = (v3d->swap_color_rb ? 666bf215546Sopenharmony_ci v3d->blend_color.hf[0] : 667bf215546Sopenharmony_ci v3d->blend_color.hf[2]); 668bf215546Sopenharmony_ci color.alpha_f16 = v3d->blend_color.hf[3]; 669bf215546Sopenharmony_ci } 670bf215546Sopenharmony_ci } 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci if (v3d->dirty & (V3D_DIRTY_ZSA | V3D_DIRTY_STENCIL_REF)) { 673bf215546Sopenharmony_ci struct pipe_stencil_state *front = &v3d->zsa->base.stencil[0]; 674bf215546Sopenharmony_ci struct pipe_stencil_state *back = &v3d->zsa->base.stencil[1]; 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ci if (front->enabled) { 677bf215546Sopenharmony_ci cl_emit_with_prepacked(&job->bcl, STENCIL_CFG, 678bf215546Sopenharmony_ci v3d->zsa->stencil_front, config) { 679bf215546Sopenharmony_ci config.stencil_ref_value = 680bf215546Sopenharmony_ci v3d->stencil_ref.ref_value[0]; 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci } 683bf215546Sopenharmony_ci 684bf215546Sopenharmony_ci if (back->enabled) { 685bf215546Sopenharmony_ci cl_emit_with_prepacked(&job->bcl, STENCIL_CFG, 686bf215546Sopenharmony_ci v3d->zsa->stencil_back, config) { 687bf215546Sopenharmony_ci config.stencil_ref_value = 688bf215546Sopenharmony_ci v3d->stencil_ref.ref_value[1]; 689bf215546Sopenharmony_ci } 690bf215546Sopenharmony_ci } 691bf215546Sopenharmony_ci } 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci#if V3D_VERSION < 40 694bf215546Sopenharmony_ci /* Pre-4.x, we have texture state that depends on both the sampler and 695bf215546Sopenharmony_ci * the view, so we merge them together at draw time. 696bf215546Sopenharmony_ci */ 697bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_FRAGTEX) 698bf215546Sopenharmony_ci emit_textures(v3d, &v3d->tex[PIPE_SHADER_FRAGMENT]); 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_GEOMTEX) 701bf215546Sopenharmony_ci emit_textures(v3d, &v3d->tex[PIPE_SHADER_GEOMETRY]); 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_VERTTEX) 704bf215546Sopenharmony_ci emit_textures(v3d, &v3d->tex[PIPE_SHADER_VERTEX]); 705bf215546Sopenharmony_ci#endif 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_FLAT_SHADE_FLAGS) { 708bf215546Sopenharmony_ci if (!emit_varying_flags(job, 709bf215546Sopenharmony_ci v3d->prog.fs->prog_data.fs->flat_shade_flags, 710bf215546Sopenharmony_ci emit_flat_shade_flags)) { 711bf215546Sopenharmony_ci cl_emit(&job->bcl, ZERO_ALL_FLAT_SHADE_FLAGS, flags); 712bf215546Sopenharmony_ci } 713bf215546Sopenharmony_ci } 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci#if V3D_VERSION >= 40 716bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_NOPERSPECTIVE_FLAGS) { 717bf215546Sopenharmony_ci if (!emit_varying_flags(job, 718bf215546Sopenharmony_ci v3d->prog.fs->prog_data.fs->noperspective_flags, 719bf215546Sopenharmony_ci emit_noperspective_flags)) { 720bf215546Sopenharmony_ci cl_emit(&job->bcl, ZERO_ALL_NON_PERSPECTIVE_FLAGS, flags); 721bf215546Sopenharmony_ci } 722bf215546Sopenharmony_ci } 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_CENTROID_FLAGS) { 725bf215546Sopenharmony_ci if (!emit_varying_flags(job, 726bf215546Sopenharmony_ci v3d->prog.fs->prog_data.fs->centroid_flags, 727bf215546Sopenharmony_ci emit_centroid_flags)) { 728bf215546Sopenharmony_ci cl_emit(&job->bcl, ZERO_ALL_CENTROID_FLAGS, flags); 729bf215546Sopenharmony_ci } 730bf215546Sopenharmony_ci } 731bf215546Sopenharmony_ci#endif 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_ci /* Set up the transform feedback data specs (which VPM entries to 734bf215546Sopenharmony_ci * output to which buffers). 735bf215546Sopenharmony_ci */ 736bf215546Sopenharmony_ci if (v3d->dirty & (V3D_DIRTY_STREAMOUT | 737bf215546Sopenharmony_ci V3D_DIRTY_RASTERIZER | 738bf215546Sopenharmony_ci V3D_DIRTY_PRIM_MODE)) { 739bf215546Sopenharmony_ci struct v3d_streamout_stateobj *so = &v3d->streamout; 740bf215546Sopenharmony_ci if (so->num_targets) { 741bf215546Sopenharmony_ci bool psiz_per_vertex = (v3d->prim_mode == PIPE_PRIM_POINTS && 742bf215546Sopenharmony_ci v3d->rasterizer->base.point_size_per_vertex); 743bf215546Sopenharmony_ci struct v3d_uncompiled_shader *tf_shader = 744bf215546Sopenharmony_ci get_tf_shader(v3d); 745bf215546Sopenharmony_ci uint16_t *tf_specs = (psiz_per_vertex ? 746bf215546Sopenharmony_ci tf_shader->tf_specs_psiz : 747bf215546Sopenharmony_ci tf_shader->tf_specs); 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci#if V3D_VERSION >= 40 750bf215546Sopenharmony_ci bool tf_enabled = v3d_transform_feedback_enabled(v3d); 751bf215546Sopenharmony_ci job->tf_enabled |= tf_enabled; 752bf215546Sopenharmony_ci 753bf215546Sopenharmony_ci cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) { 754bf215546Sopenharmony_ci tfe.number_of_16_bit_output_data_specs_following = 755bf215546Sopenharmony_ci tf_shader->num_tf_specs; 756bf215546Sopenharmony_ci tfe.enable = tf_enabled; 757bf215546Sopenharmony_ci }; 758bf215546Sopenharmony_ci#else /* V3D_VERSION < 40 */ 759bf215546Sopenharmony_ci cl_emit(&job->bcl, TRANSFORM_FEEDBACK_ENABLE, tfe) { 760bf215546Sopenharmony_ci tfe.number_of_32_bit_output_buffer_address_following = 761bf215546Sopenharmony_ci so->num_targets; 762bf215546Sopenharmony_ci tfe.number_of_16_bit_output_data_specs_following = 763bf215546Sopenharmony_ci tf_shader->num_tf_specs; 764bf215546Sopenharmony_ci }; 765bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */ 766bf215546Sopenharmony_ci for (int i = 0; i < tf_shader->num_tf_specs; i++) { 767bf215546Sopenharmony_ci cl_emit_prepacked(&job->bcl, &tf_specs[i]); 768bf215546Sopenharmony_ci } 769bf215546Sopenharmony_ci } else { 770bf215546Sopenharmony_ci#if V3D_VERSION >= 40 771bf215546Sopenharmony_ci cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) { 772bf215546Sopenharmony_ci tfe.enable = false; 773bf215546Sopenharmony_ci }; 774bf215546Sopenharmony_ci#endif /* V3D_VERSION >= 40 */ 775bf215546Sopenharmony_ci } 776bf215546Sopenharmony_ci } 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci /* Set up the transform feedback buffers. */ 779bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_STREAMOUT) { 780bf215546Sopenharmony_ci struct v3d_uncompiled_shader *tf_shader = get_tf_shader(v3d); 781bf215546Sopenharmony_ci struct v3d_streamout_stateobj *so = &v3d->streamout; 782bf215546Sopenharmony_ci for (int i = 0; i < so->num_targets; i++) { 783bf215546Sopenharmony_ci const struct pipe_stream_output_target *target = 784bf215546Sopenharmony_ci so->targets[i]; 785bf215546Sopenharmony_ci struct v3d_resource *rsc = target ? 786bf215546Sopenharmony_ci v3d_resource(target->buffer) : NULL; 787bf215546Sopenharmony_ci struct pipe_shader_state *ss = &tf_shader->base; 788bf215546Sopenharmony_ci struct pipe_stream_output_info *info = &ss->stream_output; 789bf215546Sopenharmony_ci uint32_t offset = (v3d->streamout.offsets[i] * 790bf215546Sopenharmony_ci info->stride[i] * 4); 791bf215546Sopenharmony_ci 792bf215546Sopenharmony_ci#if V3D_VERSION >= 40 793bf215546Sopenharmony_ci if (!target) 794bf215546Sopenharmony_ci continue; 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_ci cl_emit(&job->bcl, TRANSFORM_FEEDBACK_BUFFER, output) { 797bf215546Sopenharmony_ci output.buffer_address = 798bf215546Sopenharmony_ci cl_address(rsc->bo, 799bf215546Sopenharmony_ci target->buffer_offset + 800bf215546Sopenharmony_ci offset); 801bf215546Sopenharmony_ci output.buffer_size_in_32_bit_words = 802bf215546Sopenharmony_ci (target->buffer_size - offset) >> 2; 803bf215546Sopenharmony_ci output.buffer_number = i; 804bf215546Sopenharmony_ci } 805bf215546Sopenharmony_ci#else /* V3D_VERSION < 40 */ 806bf215546Sopenharmony_ci cl_emit(&job->bcl, TRANSFORM_FEEDBACK_OUTPUT_ADDRESS, output) { 807bf215546Sopenharmony_ci if (target) { 808bf215546Sopenharmony_ci output.address = 809bf215546Sopenharmony_ci cl_address(rsc->bo, 810bf215546Sopenharmony_ci target->buffer_offset + 811bf215546Sopenharmony_ci offset); 812bf215546Sopenharmony_ci } 813bf215546Sopenharmony_ci }; 814bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */ 815bf215546Sopenharmony_ci if (target) { 816bf215546Sopenharmony_ci v3d_job_add_tf_write_resource(v3d->job, 817bf215546Sopenharmony_ci target->buffer); 818bf215546Sopenharmony_ci } 819bf215546Sopenharmony_ci /* XXX: buffer_size? */ 820bf215546Sopenharmony_ci } 821bf215546Sopenharmony_ci } 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_OQ) { 824bf215546Sopenharmony_ci cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter) { 825bf215546Sopenharmony_ci if (v3d->active_queries && v3d->current_oq) { 826bf215546Sopenharmony_ci counter.address = cl_address(v3d->current_oq, 0); 827bf215546Sopenharmony_ci } 828bf215546Sopenharmony_ci } 829bf215546Sopenharmony_ci } 830bf215546Sopenharmony_ci 831bf215546Sopenharmony_ci#if V3D_VERSION >= 40 832bf215546Sopenharmony_ci if (v3d->dirty & V3D_DIRTY_SAMPLE_STATE) { 833bf215546Sopenharmony_ci cl_emit(&job->bcl, SAMPLE_STATE, state) { 834bf215546Sopenharmony_ci /* Note: SampleCoverage was handled at the 835bf215546Sopenharmony_ci * frontend level by converting to sample_mask. 836bf215546Sopenharmony_ci */ 837bf215546Sopenharmony_ci state.coverage = 1.0; 838bf215546Sopenharmony_ci state.mask = job->msaa ? v3d->sample_mask : 0xf; 839bf215546Sopenharmony_ci } 840bf215546Sopenharmony_ci } 841bf215546Sopenharmony_ci#endif 842bf215546Sopenharmony_ci} 843