101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2014-2017 Broadcom 301e04c3fSmrg * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 401e04c3fSmrg * 501e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 601e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 701e04c3fSmrg * to deal in the Software without restriction, including without limitation 801e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 901e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 1001e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1101e04c3fSmrg * 1201e04c3fSmrg * The above copyright notice and this permission notice (including the next 1301e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1401e04c3fSmrg * Software. 1501e04c3fSmrg * 1601e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1701e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1801e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1901e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2001e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2101e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2201e04c3fSmrg * IN THE SOFTWARE. 2301e04c3fSmrg */ 2401e04c3fSmrg 2501e04c3fSmrg#include "pipe/p_state.h" 267ec681f3Smrg#include "util/format/u_format.h" 2701e04c3fSmrg#include "util/u_framebuffer.h" 2801e04c3fSmrg#include "util/u_inlines.h" 2901e04c3fSmrg#include "util/u_math.h" 3001e04c3fSmrg#include "util/u_memory.h" 317ec681f3Smrg#include "util/half_float.h" 3201e04c3fSmrg#include "util/u_helpers.h" 339f464c52Smaya#include "util/u_upload_mgr.h" 3401e04c3fSmrg 3501e04c3fSmrg#include "v3d_context.h" 367ec681f3Smrg#include "broadcom/common/v3d_tiling.h" 3701e04c3fSmrg#include "broadcom/common/v3d_macros.h" 389f464c52Smaya#include "broadcom/compiler/v3d_compiler.h" 3901e04c3fSmrg#include "broadcom/cle/v3dx_pack.h" 4001e04c3fSmrg 4101e04c3fSmrgstatic void 4201e04c3fSmrgv3d_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso) 4301e04c3fSmrg{ 4401e04c3fSmrg free(hwcso); 4501e04c3fSmrg} 4601e04c3fSmrg 4701e04c3fSmrgstatic void 4801e04c3fSmrgv3d_set_blend_color(struct pipe_context *pctx, 4901e04c3fSmrg const struct pipe_blend_color *blend_color) 5001e04c3fSmrg{ 5101e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 5201e04c3fSmrg v3d->blend_color.f = *blend_color; 5301e04c3fSmrg for (int i = 0; i < 4; i++) { 5401e04c3fSmrg v3d->blend_color.hf[i] = 557ec681f3Smrg _mesa_float_to_half(blend_color->color[i]); 5601e04c3fSmrg } 577ec681f3Smrg v3d->dirty |= V3D_DIRTY_BLEND_COLOR; 5801e04c3fSmrg} 5901e04c3fSmrg 6001e04c3fSmrgstatic void 6101e04c3fSmrgv3d_set_stencil_ref(struct pipe_context *pctx, 627ec681f3Smrg const struct pipe_stencil_ref stencil_ref) 6301e04c3fSmrg{ 6401e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 657ec681f3Smrg v3d->stencil_ref = stencil_ref; 667ec681f3Smrg v3d->dirty |= V3D_DIRTY_STENCIL_REF; 6701e04c3fSmrg} 6801e04c3fSmrg 6901e04c3fSmrgstatic void 7001e04c3fSmrgv3d_set_clip_state(struct pipe_context *pctx, 7101e04c3fSmrg const struct pipe_clip_state *clip) 7201e04c3fSmrg{ 7301e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 7401e04c3fSmrg v3d->clip = *clip; 757ec681f3Smrg v3d->dirty |= V3D_DIRTY_CLIP; 7601e04c3fSmrg} 7701e04c3fSmrg 7801e04c3fSmrgstatic void 7901e04c3fSmrgv3d_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 8001e04c3fSmrg{ 8101e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 829f464c52Smaya v3d->sample_mask = sample_mask & ((1 << V3D_MAX_SAMPLES) - 1); 837ec681f3Smrg v3d->dirty |= V3D_DIRTY_SAMPLE_STATE; 8401e04c3fSmrg} 8501e04c3fSmrg 8601e04c3fSmrgstatic void * 8701e04c3fSmrgv3d_create_rasterizer_state(struct pipe_context *pctx, 8801e04c3fSmrg const struct pipe_rasterizer_state *cso) 8901e04c3fSmrg{ 9001e04c3fSmrg struct v3d_rasterizer_state *so; 9101e04c3fSmrg 9201e04c3fSmrg so = CALLOC_STRUCT(v3d_rasterizer_state); 9301e04c3fSmrg if (!so) 9401e04c3fSmrg return NULL; 9501e04c3fSmrg 9601e04c3fSmrg so->base = *cso; 9701e04c3fSmrg 9801e04c3fSmrg /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835, 9901e04c3fSmrg * BCM21553). 10001e04c3fSmrg */ 10101e04c3fSmrg so->point_size = MAX2(cso->point_size, .125f); 10201e04c3fSmrg 10301e04c3fSmrg STATIC_ASSERT(sizeof(so->depth_offset) >= 10401e04c3fSmrg cl_packet_length(DEPTH_OFFSET)); 10501e04c3fSmrg v3dx_pack(&so->depth_offset, DEPTH_OFFSET, depth) { 10601e04c3fSmrg depth.depth_offset_factor = cso->offset_scale; 10701e04c3fSmrg depth.depth_offset_units = cso->offset_units; 10801e04c3fSmrg } 10901e04c3fSmrg 11001e04c3fSmrg /* The HW treats polygon offset units based on a Z24 buffer, so we 11101e04c3fSmrg * need to scale up offset_units if we're only Z16. 11201e04c3fSmrg */ 11301e04c3fSmrg v3dx_pack(&so->depth_offset_z16, DEPTH_OFFSET, depth) { 11401e04c3fSmrg depth.depth_offset_factor = cso->offset_scale; 11501e04c3fSmrg depth.depth_offset_units = cso->offset_units * 256.0; 11601e04c3fSmrg } 11701e04c3fSmrg 11801e04c3fSmrg return so; 11901e04c3fSmrg} 12001e04c3fSmrg 12101e04c3fSmrg/* Blend state is baked into shaders. */ 12201e04c3fSmrgstatic void * 12301e04c3fSmrgv3d_create_blend_state(struct pipe_context *pctx, 12401e04c3fSmrg const struct pipe_blend_state *cso) 12501e04c3fSmrg{ 12601e04c3fSmrg struct v3d_blend_state *so; 12701e04c3fSmrg 12801e04c3fSmrg so = CALLOC_STRUCT(v3d_blend_state); 12901e04c3fSmrg if (!so) 13001e04c3fSmrg return NULL; 13101e04c3fSmrg 13201e04c3fSmrg so->base = *cso; 13301e04c3fSmrg 13401e04c3fSmrg if (cso->independent_blend_enable) { 1359f464c52Smaya for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) { 13601e04c3fSmrg so->blend_enables |= cso->rt[i].blend_enable << i; 13701e04c3fSmrg 13801e04c3fSmrg /* V3D 4.x is when we got independent blend enables. */ 13901e04c3fSmrg assert(V3D_VERSION >= 40 || 14001e04c3fSmrg cso->rt[i].blend_enable == cso->rt[0].blend_enable); 14101e04c3fSmrg } 14201e04c3fSmrg } else { 14301e04c3fSmrg if (cso->rt[0].blend_enable) 1449f464c52Smaya so->blend_enables = (1 << V3D_MAX_DRAW_BUFFERS) - 1; 14501e04c3fSmrg } 14601e04c3fSmrg 14701e04c3fSmrg return so; 14801e04c3fSmrg} 14901e04c3fSmrg 15001e04c3fSmrgstatic uint32_t 15101e04c3fSmrgtranslate_stencil_op(enum pipe_stencil_op op) 15201e04c3fSmrg{ 15301e04c3fSmrg switch (op) { 15401e04c3fSmrg case PIPE_STENCIL_OP_KEEP: return V3D_STENCIL_OP_KEEP; 15501e04c3fSmrg case PIPE_STENCIL_OP_ZERO: return V3D_STENCIL_OP_ZERO; 15601e04c3fSmrg case PIPE_STENCIL_OP_REPLACE: return V3D_STENCIL_OP_REPLACE; 15701e04c3fSmrg case PIPE_STENCIL_OP_INCR: return V3D_STENCIL_OP_INCR; 15801e04c3fSmrg case PIPE_STENCIL_OP_DECR: return V3D_STENCIL_OP_DECR; 15901e04c3fSmrg case PIPE_STENCIL_OP_INCR_WRAP: return V3D_STENCIL_OP_INCWRAP; 16001e04c3fSmrg case PIPE_STENCIL_OP_DECR_WRAP: return V3D_STENCIL_OP_DECWRAP; 16101e04c3fSmrg case PIPE_STENCIL_OP_INVERT: return V3D_STENCIL_OP_INVERT; 16201e04c3fSmrg } 16301e04c3fSmrg unreachable("bad stencil op"); 16401e04c3fSmrg} 16501e04c3fSmrg 16601e04c3fSmrgstatic void * 16701e04c3fSmrgv3d_create_depth_stencil_alpha_state(struct pipe_context *pctx, 16801e04c3fSmrg const struct pipe_depth_stencil_alpha_state *cso) 16901e04c3fSmrg{ 17001e04c3fSmrg struct v3d_depth_stencil_alpha_state *so; 17101e04c3fSmrg 17201e04c3fSmrg so = CALLOC_STRUCT(v3d_depth_stencil_alpha_state); 17301e04c3fSmrg if (!so) 17401e04c3fSmrg return NULL; 17501e04c3fSmrg 17601e04c3fSmrg so->base = *cso; 17701e04c3fSmrg 1787ec681f3Smrg if (cso->depth_enabled) { 1797ec681f3Smrg switch (cso->depth_func) { 18001e04c3fSmrg case PIPE_FUNC_LESS: 18101e04c3fSmrg case PIPE_FUNC_LEQUAL: 1827ec681f3Smrg so->ez_state = V3D_EZ_LT_LE; 18301e04c3fSmrg break; 18401e04c3fSmrg case PIPE_FUNC_GREATER: 18501e04c3fSmrg case PIPE_FUNC_GEQUAL: 1867ec681f3Smrg so->ez_state = V3D_EZ_GT_GE; 18701e04c3fSmrg break; 18801e04c3fSmrg case PIPE_FUNC_NEVER: 18901e04c3fSmrg case PIPE_FUNC_EQUAL: 1907ec681f3Smrg so->ez_state = V3D_EZ_UNDECIDED; 19101e04c3fSmrg break; 19201e04c3fSmrg default: 1937ec681f3Smrg so->ez_state = V3D_EZ_DISABLED; 19401e04c3fSmrg break; 19501e04c3fSmrg } 19601e04c3fSmrg 19701e04c3fSmrg /* If stencil is enabled and it's not a no-op, then it would 19801e04c3fSmrg * break EZ updates. 19901e04c3fSmrg */ 20001e04c3fSmrg if (cso->stencil[0].enabled && 20101e04c3fSmrg (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP || 20201e04c3fSmrg cso->stencil[0].func != PIPE_FUNC_ALWAYS || 20301e04c3fSmrg (cso->stencil[1].enabled && 20401e04c3fSmrg (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP && 20501e04c3fSmrg cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) { 2067ec681f3Smrg so->ez_state = V3D_EZ_DISABLED; 20701e04c3fSmrg } 20801e04c3fSmrg } 20901e04c3fSmrg 21001e04c3fSmrg const struct pipe_stencil_state *front = &cso->stencil[0]; 21101e04c3fSmrg const struct pipe_stencil_state *back = &cso->stencil[1]; 21201e04c3fSmrg 21301e04c3fSmrg if (front->enabled) { 21401e04c3fSmrg STATIC_ASSERT(sizeof(so->stencil_front) >= 21501e04c3fSmrg cl_packet_length(STENCIL_CFG)); 21601e04c3fSmrg v3dx_pack(&so->stencil_front, STENCIL_CFG, config) { 21701e04c3fSmrg config.front_config = true; 21801e04c3fSmrg /* If !back->enabled, then the front values should be 21901e04c3fSmrg * used for both front and back-facing primitives. 22001e04c3fSmrg */ 22101e04c3fSmrg config.back_config = !back->enabled; 22201e04c3fSmrg 22301e04c3fSmrg config.stencil_write_mask = front->writemask; 22401e04c3fSmrg config.stencil_test_mask = front->valuemask; 22501e04c3fSmrg 22601e04c3fSmrg config.stencil_test_function = front->func; 22701e04c3fSmrg config.stencil_pass_op = 22801e04c3fSmrg translate_stencil_op(front->zpass_op); 22901e04c3fSmrg config.depth_test_fail_op = 23001e04c3fSmrg translate_stencil_op(front->zfail_op); 23101e04c3fSmrg config.stencil_test_fail_op = 23201e04c3fSmrg translate_stencil_op(front->fail_op); 23301e04c3fSmrg } 23401e04c3fSmrg } 23501e04c3fSmrg if (back->enabled) { 23601e04c3fSmrg STATIC_ASSERT(sizeof(so->stencil_back) >= 23701e04c3fSmrg cl_packet_length(STENCIL_CFG)); 23801e04c3fSmrg v3dx_pack(&so->stencil_back, STENCIL_CFG, config) { 23901e04c3fSmrg config.front_config = false; 24001e04c3fSmrg config.back_config = true; 24101e04c3fSmrg 24201e04c3fSmrg config.stencil_write_mask = back->writemask; 24301e04c3fSmrg config.stencil_test_mask = back->valuemask; 24401e04c3fSmrg 24501e04c3fSmrg config.stencil_test_function = back->func; 24601e04c3fSmrg config.stencil_pass_op = 24701e04c3fSmrg translate_stencil_op(back->zpass_op); 24801e04c3fSmrg config.depth_test_fail_op = 24901e04c3fSmrg translate_stencil_op(back->zfail_op); 25001e04c3fSmrg config.stencil_test_fail_op = 25101e04c3fSmrg translate_stencil_op(back->fail_op); 25201e04c3fSmrg } 25301e04c3fSmrg } 25401e04c3fSmrg 25501e04c3fSmrg return so; 25601e04c3fSmrg} 25701e04c3fSmrg 25801e04c3fSmrgstatic void 25901e04c3fSmrgv3d_set_polygon_stipple(struct pipe_context *pctx, 26001e04c3fSmrg const struct pipe_poly_stipple *stipple) 26101e04c3fSmrg{ 26201e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 26301e04c3fSmrg v3d->stipple = *stipple; 2647ec681f3Smrg v3d->dirty |= V3D_DIRTY_STIPPLE; 26501e04c3fSmrg} 26601e04c3fSmrg 26701e04c3fSmrgstatic void 26801e04c3fSmrgv3d_set_scissor_states(struct pipe_context *pctx, 26901e04c3fSmrg unsigned start_slot, 27001e04c3fSmrg unsigned num_scissors, 27101e04c3fSmrg const struct pipe_scissor_state *scissor) 27201e04c3fSmrg{ 27301e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 27401e04c3fSmrg 27501e04c3fSmrg v3d->scissor = *scissor; 2767ec681f3Smrg v3d->dirty |= V3D_DIRTY_SCISSOR; 27701e04c3fSmrg} 27801e04c3fSmrg 27901e04c3fSmrgstatic void 28001e04c3fSmrgv3d_set_viewport_states(struct pipe_context *pctx, 28101e04c3fSmrg unsigned start_slot, 28201e04c3fSmrg unsigned num_viewports, 28301e04c3fSmrg const struct pipe_viewport_state *viewport) 28401e04c3fSmrg{ 28501e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 28601e04c3fSmrg v3d->viewport = *viewport; 2877ec681f3Smrg v3d->dirty |= V3D_DIRTY_VIEWPORT; 28801e04c3fSmrg} 28901e04c3fSmrg 29001e04c3fSmrgstatic void 29101e04c3fSmrgv3d_set_vertex_buffers(struct pipe_context *pctx, 29201e04c3fSmrg unsigned start_slot, unsigned count, 2937ec681f3Smrg unsigned unbind_num_trailing_slots, 2947ec681f3Smrg bool take_ownership, 29501e04c3fSmrg const struct pipe_vertex_buffer *vb) 29601e04c3fSmrg{ 29701e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 29801e04c3fSmrg struct v3d_vertexbuf_stateobj *so = &v3d->vertexbuf; 29901e04c3fSmrg 30001e04c3fSmrg util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, 3017ec681f3Smrg start_slot, count, 3027ec681f3Smrg unbind_num_trailing_slots, 3037ec681f3Smrg take_ownership); 30401e04c3fSmrg so->count = util_last_bit(so->enabled_mask); 30501e04c3fSmrg 3067ec681f3Smrg v3d->dirty |= V3D_DIRTY_VTXBUF; 30701e04c3fSmrg} 30801e04c3fSmrg 30901e04c3fSmrgstatic void 31001e04c3fSmrgv3d_blend_state_bind(struct pipe_context *pctx, void *hwcso) 31101e04c3fSmrg{ 31201e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 31301e04c3fSmrg v3d->blend = hwcso; 3147ec681f3Smrg v3d->dirty |= V3D_DIRTY_BLEND; 31501e04c3fSmrg} 31601e04c3fSmrg 31701e04c3fSmrgstatic void 31801e04c3fSmrgv3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) 31901e04c3fSmrg{ 32001e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 32101e04c3fSmrg v3d->rasterizer = hwcso; 3227ec681f3Smrg v3d->dirty |= V3D_DIRTY_RASTERIZER; 32301e04c3fSmrg} 32401e04c3fSmrg 32501e04c3fSmrgstatic void 32601e04c3fSmrgv3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso) 32701e04c3fSmrg{ 32801e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 32901e04c3fSmrg v3d->zsa = hwcso; 3307ec681f3Smrg v3d->dirty |= V3D_DIRTY_ZSA; 33101e04c3fSmrg} 33201e04c3fSmrg 33301e04c3fSmrgstatic void * 33401e04c3fSmrgv3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements, 33501e04c3fSmrg const struct pipe_vertex_element *elements) 33601e04c3fSmrg{ 33701e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 33801e04c3fSmrg struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj); 33901e04c3fSmrg 34001e04c3fSmrg if (!so) 34101e04c3fSmrg return NULL; 34201e04c3fSmrg 34301e04c3fSmrg memcpy(so->pipe, elements, sizeof(*elements) * num_elements); 34401e04c3fSmrg so->num_elements = num_elements; 34501e04c3fSmrg 34601e04c3fSmrg for (int i = 0; i < so->num_elements; i++) { 34701e04c3fSmrg const struct pipe_vertex_element *elem = &elements[i]; 34801e04c3fSmrg const struct util_format_description *desc = 34901e04c3fSmrg util_format_description(elem->src_format); 35001e04c3fSmrg uint32_t r_size = desc->channel[0].size; 35101e04c3fSmrg 35201e04c3fSmrg const uint32_t size = 35301e04c3fSmrg cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD); 35401e04c3fSmrg 35501e04c3fSmrg v3dx_pack(&so->attrs[i * size], 35601e04c3fSmrg GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) { 35701e04c3fSmrg /* vec_size == 0 means 4 */ 35801e04c3fSmrg attr.vec_size = desc->nr_channels & 3; 35901e04c3fSmrg attr.signed_int_type = (desc->channel[0].type == 36001e04c3fSmrg UTIL_FORMAT_TYPE_SIGNED); 36101e04c3fSmrg 36201e04c3fSmrg attr.normalized_int_type = desc->channel[0].normalized; 36301e04c3fSmrg attr.read_as_int_uint = desc->channel[0].pure_integer; 36401e04c3fSmrg attr.instance_divisor = MIN2(elem->instance_divisor, 36501e04c3fSmrg 0xffff); 36601e04c3fSmrg 36701e04c3fSmrg switch (desc->channel[0].type) { 36801e04c3fSmrg case UTIL_FORMAT_TYPE_FLOAT: 36901e04c3fSmrg if (r_size == 32) { 37001e04c3fSmrg attr.type = ATTRIBUTE_FLOAT; 37101e04c3fSmrg } else { 37201e04c3fSmrg assert(r_size == 16); 37301e04c3fSmrg attr.type = ATTRIBUTE_HALF_FLOAT; 37401e04c3fSmrg } 37501e04c3fSmrg break; 37601e04c3fSmrg 37701e04c3fSmrg case UTIL_FORMAT_TYPE_SIGNED: 37801e04c3fSmrg case UTIL_FORMAT_TYPE_UNSIGNED: 37901e04c3fSmrg switch (r_size) { 38001e04c3fSmrg case 32: 38101e04c3fSmrg attr.type = ATTRIBUTE_INT; 38201e04c3fSmrg break; 38301e04c3fSmrg case 16: 38401e04c3fSmrg attr.type = ATTRIBUTE_SHORT; 38501e04c3fSmrg break; 38601e04c3fSmrg case 10: 38701e04c3fSmrg attr.type = ATTRIBUTE_INT2_10_10_10; 38801e04c3fSmrg break; 38901e04c3fSmrg case 8: 39001e04c3fSmrg attr.type = ATTRIBUTE_BYTE; 39101e04c3fSmrg break; 39201e04c3fSmrg default: 39301e04c3fSmrg fprintf(stderr, 39401e04c3fSmrg "format %s unsupported\n", 39501e04c3fSmrg desc->name); 39601e04c3fSmrg attr.type = ATTRIBUTE_BYTE; 39701e04c3fSmrg abort(); 39801e04c3fSmrg } 39901e04c3fSmrg break; 40001e04c3fSmrg 40101e04c3fSmrg default: 40201e04c3fSmrg fprintf(stderr, 40301e04c3fSmrg "format %s unsupported\n", 40401e04c3fSmrg desc->name); 40501e04c3fSmrg abort(); 40601e04c3fSmrg } 40701e04c3fSmrg } 40801e04c3fSmrg } 40901e04c3fSmrg 41001e04c3fSmrg /* Set up the default attribute values in case any of the vertex 41101e04c3fSmrg * elements use them. 41201e04c3fSmrg */ 4139f464c52Smaya uint32_t *attrs; 4149f464c52Smaya u_upload_alloc(v3d->state_uploader, 0, 4159f464c52Smaya V3D_MAX_VS_INPUTS * sizeof(float), 16, 4169f464c52Smaya &so->defaults_offset, &so->defaults, (void **)&attrs); 4179f464c52Smaya 4189f464c52Smaya for (int i = 0; i < V3D_MAX_VS_INPUTS / 4; i++) { 41901e04c3fSmrg attrs[i * 4 + 0] = 0; 42001e04c3fSmrg attrs[i * 4 + 1] = 0; 42101e04c3fSmrg attrs[i * 4 + 2] = 0; 42201e04c3fSmrg if (i < so->num_elements && 42301e04c3fSmrg util_format_is_pure_integer(so->pipe[i].src_format)) { 42401e04c3fSmrg attrs[i * 4 + 3] = 1; 42501e04c3fSmrg } else { 42601e04c3fSmrg attrs[i * 4 + 3] = fui(1.0); 42701e04c3fSmrg } 42801e04c3fSmrg } 42901e04c3fSmrg 4309f464c52Smaya u_upload_unmap(v3d->state_uploader); 43101e04c3fSmrg return so; 43201e04c3fSmrg} 43301e04c3fSmrg 43401e04c3fSmrgstatic void 43501e04c3fSmrgv3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso) 43601e04c3fSmrg{ 43701e04c3fSmrg struct v3d_vertex_stateobj *so = hwcso; 43801e04c3fSmrg 4399f464c52Smaya pipe_resource_reference(&so->defaults, NULL); 44001e04c3fSmrg free(so); 44101e04c3fSmrg} 44201e04c3fSmrg 44301e04c3fSmrgstatic void 44401e04c3fSmrgv3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso) 44501e04c3fSmrg{ 44601e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 44701e04c3fSmrg v3d->vtx = hwcso; 4487ec681f3Smrg v3d->dirty |= V3D_DIRTY_VTXSTATE; 44901e04c3fSmrg} 45001e04c3fSmrg 45101e04c3fSmrgstatic void 45201e04c3fSmrgv3d_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index, 4537ec681f3Smrg bool take_ownership, 45401e04c3fSmrg const struct pipe_constant_buffer *cb) 45501e04c3fSmrg{ 45601e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 45701e04c3fSmrg struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader]; 45801e04c3fSmrg 4597ec681f3Smrg util_copy_constant_buffer(&so->cb[index], cb, take_ownership); 46001e04c3fSmrg 4617ec681f3Smrg /* Note that the gallium frontend can unbind constant buffers by 46201e04c3fSmrg * passing NULL here. 46301e04c3fSmrg */ 46401e04c3fSmrg if (unlikely(!cb)) { 46501e04c3fSmrg so->enabled_mask &= ~(1 << index); 46601e04c3fSmrg so->dirty_mask &= ~(1 << index); 46701e04c3fSmrg return; 46801e04c3fSmrg } 46901e04c3fSmrg 47001e04c3fSmrg so->enabled_mask |= 1 << index; 47101e04c3fSmrg so->dirty_mask |= 1 << index; 4727ec681f3Smrg v3d->dirty |= V3D_DIRTY_CONSTBUF; 47301e04c3fSmrg} 47401e04c3fSmrg 47501e04c3fSmrgstatic void 47601e04c3fSmrgv3d_set_framebuffer_state(struct pipe_context *pctx, 47701e04c3fSmrg const struct pipe_framebuffer_state *framebuffer) 47801e04c3fSmrg{ 47901e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 48001e04c3fSmrg struct pipe_framebuffer_state *cso = &v3d->framebuffer; 48101e04c3fSmrg 48201e04c3fSmrg v3d->job = NULL; 48301e04c3fSmrg 48401e04c3fSmrg util_copy_framebuffer_state(cso, framebuffer); 48501e04c3fSmrg 48601e04c3fSmrg v3d->swap_color_rb = 0; 48701e04c3fSmrg v3d->blend_dst_alpha_one = 0; 48801e04c3fSmrg for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) { 48901e04c3fSmrg struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i]; 49001e04c3fSmrg if (!cbuf) 49101e04c3fSmrg continue; 4929f464c52Smaya struct v3d_surface *v3d_cbuf = v3d_surface(cbuf); 49301e04c3fSmrg 49401e04c3fSmrg const struct util_format_description *desc = 49501e04c3fSmrg util_format_description(cbuf->format); 49601e04c3fSmrg 49701e04c3fSmrg /* For BGRA8 formats (DRI window system default format), we 4989f464c52Smaya * need to swap R and B, since the HW's format is RGBA8. On 4999f464c52Smaya * V3D 4.1+, the RCL can swap R and B on load/store. 50001e04c3fSmrg */ 5019f464c52Smaya if (v3d->screen->devinfo.ver < 41 && v3d_cbuf->swap_rb) 50201e04c3fSmrg v3d->swap_color_rb |= 1 << i; 50301e04c3fSmrg 50401e04c3fSmrg if (desc->swizzle[3] == PIPE_SWIZZLE_1) 50501e04c3fSmrg v3d->blend_dst_alpha_one |= 1 << i; 50601e04c3fSmrg } 50701e04c3fSmrg 5087ec681f3Smrg v3d->dirty |= V3D_DIRTY_FRAMEBUFFER; 50901e04c3fSmrg} 51001e04c3fSmrg 5119f464c52Smayastatic enum V3DX(Wrap_Mode) 5127ec681f3Smrgtranslate_wrap(uint32_t pipe_wrap) 51301e04c3fSmrg{ 51401e04c3fSmrg switch (pipe_wrap) { 51501e04c3fSmrg case PIPE_TEX_WRAP_REPEAT: 5169f464c52Smaya return V3D_WRAP_MODE_REPEAT; 51701e04c3fSmrg case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 5189f464c52Smaya return V3D_WRAP_MODE_CLAMP; 51901e04c3fSmrg case PIPE_TEX_WRAP_MIRROR_REPEAT: 5209f464c52Smaya return V3D_WRAP_MODE_MIRROR; 52101e04c3fSmrg case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 5229f464c52Smaya return V3D_WRAP_MODE_BORDER; 5237ec681f3Smrg case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 5247ec681f3Smrg return V3D_WRAP_MODE_MIRROR_ONCE; 52501e04c3fSmrg default: 52601e04c3fSmrg unreachable("Unknown wrap mode"); 52701e04c3fSmrg } 52801e04c3fSmrg} 52901e04c3fSmrg 53001e04c3fSmrg#if V3D_VERSION >= 40 5319f464c52Smayastatic void 5329f464c52Smayav3d_upload_sampler_state_variant(void *map, 5339f464c52Smaya const struct pipe_sampler_state *cso, 5347ec681f3Smrg enum v3d_sampler_state_variant variant) 5359f464c52Smaya{ 53601e04c3fSmrg v3dx_pack(map, SAMPLER_STATE, sampler) { 53701e04c3fSmrg sampler.wrap_i_border = false; 53801e04c3fSmrg 5397ec681f3Smrg sampler.wrap_s = translate_wrap(cso->wrap_s); 5407ec681f3Smrg sampler.wrap_t = translate_wrap(cso->wrap_t); 5417ec681f3Smrg sampler.wrap_r = translate_wrap(cso->wrap_r); 54201e04c3fSmrg 54301e04c3fSmrg sampler.fixed_bias = cso->lod_bias; 54401e04c3fSmrg sampler.depth_compare_function = cso->compare_func; 54501e04c3fSmrg 54601e04c3fSmrg sampler.min_filter_nearest = 54701e04c3fSmrg cso->min_img_filter == PIPE_TEX_FILTER_NEAREST; 54801e04c3fSmrg sampler.mag_filter_nearest = 54901e04c3fSmrg cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST; 55001e04c3fSmrg sampler.mip_filter_nearest = 55101e04c3fSmrg cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR; 55201e04c3fSmrg 55301e04c3fSmrg sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod), 55401e04c3fSmrg 15); 5557ec681f3Smrg sampler.max_level_of_detail = MIN2(MAX2(cso->max_lod, 5567ec681f3Smrg cso->min_lod), 15); 55701e04c3fSmrg 55801e04c3fSmrg /* If we're not doing inter-miplevel filtering, we need to 55901e04c3fSmrg * clamp the LOD so that we only sample from baselevel. 56001e04c3fSmrg * However, we need to still allow the calculated LOD to be 56101e04c3fSmrg * fractionally over the baselevel, so that the HW can decide 56201e04c3fSmrg * between the min and mag filters. 56301e04c3fSmrg */ 56401e04c3fSmrg if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 56501e04c3fSmrg sampler.min_level_of_detail = 56601e04c3fSmrg MIN2(sampler.min_level_of_detail, 1.0 / 256.0); 56701e04c3fSmrg sampler.max_level_of_detail = 56801e04c3fSmrg MIN2(sampler.max_level_of_detail, 1.0 / 256.0); 56901e04c3fSmrg } 57001e04c3fSmrg 57101e04c3fSmrg if (cso->max_anisotropy) { 57201e04c3fSmrg sampler.anisotropy_enable = true; 57301e04c3fSmrg 57401e04c3fSmrg if (cso->max_anisotropy > 8) 57501e04c3fSmrg sampler.maximum_anisotropy = 3; 57601e04c3fSmrg else if (cso->max_anisotropy > 4) 57701e04c3fSmrg sampler.maximum_anisotropy = 2; 57801e04c3fSmrg else if (cso->max_anisotropy > 2) 57901e04c3fSmrg sampler.maximum_anisotropy = 1; 58001e04c3fSmrg } 58101e04c3fSmrg 5829f464c52Smaya if (variant == V3D_SAMPLER_STATE_BORDER_0) { 5839f464c52Smaya sampler.border_color_mode = V3D_BORDER_COLOR_0000; 5849f464c52Smaya } else { 5859f464c52Smaya sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS; 5869f464c52Smaya 5879f464c52Smaya union pipe_color_union border; 5889f464c52Smaya 5899f464c52Smaya /* First, reswizzle the border color for any 5909f464c52Smaya * mismatching we're doing between the texture's 5919f464c52Smaya * channel order in hardware (R) versus what it is at 5929f464c52Smaya * the GL level (ALPHA) 5939f464c52Smaya */ 5949f464c52Smaya switch (variant) { 5959f464c52Smaya case V3D_SAMPLER_STATE_F16_BGRA: 5969f464c52Smaya case V3D_SAMPLER_STATE_F16_BGRA_UNORM: 5979f464c52Smaya case V3D_SAMPLER_STATE_F16_BGRA_SNORM: 5989f464c52Smaya border.i[0] = cso->border_color.i[2]; 5999f464c52Smaya border.i[1] = cso->border_color.i[1]; 6009f464c52Smaya border.i[2] = cso->border_color.i[0]; 6019f464c52Smaya border.i[3] = cso->border_color.i[3]; 6029f464c52Smaya break; 6039f464c52Smaya 6049f464c52Smaya case V3D_SAMPLER_STATE_F16_A: 6059f464c52Smaya case V3D_SAMPLER_STATE_F16_A_UNORM: 6069f464c52Smaya case V3D_SAMPLER_STATE_F16_A_SNORM: 6079f464c52Smaya case V3D_SAMPLER_STATE_32_A: 6089f464c52Smaya case V3D_SAMPLER_STATE_32_A_UNORM: 6099f464c52Smaya case V3D_SAMPLER_STATE_32_A_SNORM: 6109f464c52Smaya border.i[0] = cso->border_color.i[3]; 6119f464c52Smaya border.i[1] = 0; 6129f464c52Smaya border.i[2] = 0; 6139f464c52Smaya border.i[3] = 0; 6149f464c52Smaya break; 6159f464c52Smaya 6169f464c52Smaya case V3D_SAMPLER_STATE_F16_LA: 6179f464c52Smaya case V3D_SAMPLER_STATE_F16_LA_UNORM: 6189f464c52Smaya case V3D_SAMPLER_STATE_F16_LA_SNORM: 6199f464c52Smaya border.i[0] = cso->border_color.i[0]; 6209f464c52Smaya border.i[1] = cso->border_color.i[3]; 6219f464c52Smaya border.i[2] = 0; 6229f464c52Smaya border.i[3] = 0; 6239f464c52Smaya break; 6249f464c52Smaya 6259f464c52Smaya default: 6269f464c52Smaya border = cso->border_color; 6279f464c52Smaya } 6289f464c52Smaya 6299f464c52Smaya /* Perform any clamping. */ 6309f464c52Smaya switch (variant) { 6319f464c52Smaya case V3D_SAMPLER_STATE_F16_UNORM: 6329f464c52Smaya case V3D_SAMPLER_STATE_F16_BGRA_UNORM: 6339f464c52Smaya case V3D_SAMPLER_STATE_F16_A_UNORM: 6349f464c52Smaya case V3D_SAMPLER_STATE_F16_LA_UNORM: 6359f464c52Smaya case V3D_SAMPLER_STATE_32_UNORM: 6369f464c52Smaya case V3D_SAMPLER_STATE_32_A_UNORM: 6379f464c52Smaya for (int i = 0; i < 4; i++) 6389f464c52Smaya border.f[i] = CLAMP(border.f[i], 0, 1); 6399f464c52Smaya break; 6409f464c52Smaya 6419f464c52Smaya case V3D_SAMPLER_STATE_F16_SNORM: 6429f464c52Smaya case V3D_SAMPLER_STATE_F16_BGRA_SNORM: 6439f464c52Smaya case V3D_SAMPLER_STATE_F16_A_SNORM: 6449f464c52Smaya case V3D_SAMPLER_STATE_F16_LA_SNORM: 6459f464c52Smaya case V3D_SAMPLER_STATE_32_SNORM: 6469f464c52Smaya case V3D_SAMPLER_STATE_32_A_SNORM: 6479f464c52Smaya for (int i = 0; i < 4; i++) 6489f464c52Smaya border.f[i] = CLAMP(border.f[i], -1, 1); 6499f464c52Smaya break; 6509f464c52Smaya 6519f464c52Smaya case V3D_SAMPLER_STATE_1010102U: 6529f464c52Smaya border.ui[0] = CLAMP(border.ui[0], 6539f464c52Smaya 0, (1 << 10) - 1); 6549f464c52Smaya border.ui[1] = CLAMP(border.ui[1], 6559f464c52Smaya 0, (1 << 10) - 1); 6569f464c52Smaya border.ui[2] = CLAMP(border.ui[2], 6579f464c52Smaya 0, (1 << 10) - 1); 6589f464c52Smaya border.ui[3] = CLAMP(border.ui[3], 6599f464c52Smaya 0, 3); 6609f464c52Smaya break; 6619f464c52Smaya 6629f464c52Smaya case V3D_SAMPLER_STATE_16U: 6639f464c52Smaya for (int i = 0; i < 4; i++) 6649f464c52Smaya border.ui[i] = CLAMP(border.ui[i], 6659f464c52Smaya 0, 0xffff); 6669f464c52Smaya break; 6679f464c52Smaya 6689f464c52Smaya case V3D_SAMPLER_STATE_16I: 6699f464c52Smaya for (int i = 0; i < 4; i++) 6709f464c52Smaya border.i[i] = CLAMP(border.i[i], 6719f464c52Smaya -32768, 32767); 6729f464c52Smaya break; 6739f464c52Smaya 6749f464c52Smaya case V3D_SAMPLER_STATE_8U: 6759f464c52Smaya for (int i = 0; i < 4; i++) 6769f464c52Smaya border.ui[i] = CLAMP(border.ui[i], 6779f464c52Smaya 0, 0xff); 6789f464c52Smaya break; 6799f464c52Smaya 6809f464c52Smaya case V3D_SAMPLER_STATE_8I: 6819f464c52Smaya for (int i = 0; i < 4; i++) 6829f464c52Smaya border.i[i] = CLAMP(border.i[i], 6839f464c52Smaya -128, 127); 6849f464c52Smaya break; 6859f464c52Smaya 6869f464c52Smaya default: 6879f464c52Smaya break; 6889f464c52Smaya } 6899f464c52Smaya 6909f464c52Smaya if (variant >= V3D_SAMPLER_STATE_32) { 6919f464c52Smaya sampler.border_color_word_0 = border.ui[0]; 6929f464c52Smaya sampler.border_color_word_1 = border.ui[1]; 6939f464c52Smaya sampler.border_color_word_2 = border.ui[2]; 6949f464c52Smaya sampler.border_color_word_3 = border.ui[3]; 6959f464c52Smaya } else { 6969f464c52Smaya sampler.border_color_word_0 = 6977ec681f3Smrg _mesa_float_to_half(border.f[0]); 6989f464c52Smaya sampler.border_color_word_1 = 6997ec681f3Smrg _mesa_float_to_half(border.f[1]); 7009f464c52Smaya sampler.border_color_word_2 = 7017ec681f3Smrg _mesa_float_to_half(border.f[2]); 7029f464c52Smaya sampler.border_color_word_3 = 7037ec681f3Smrg _mesa_float_to_half(border.f[3]); 7049f464c52Smaya } 7059f464c52Smaya } 7069f464c52Smaya } 7079f464c52Smaya} 7089f464c52Smaya#endif 7099f464c52Smaya 7109f464c52Smayastatic void * 7119f464c52Smayav3d_create_sampler_state(struct pipe_context *pctx, 7129f464c52Smaya const struct pipe_sampler_state *cso) 7139f464c52Smaya{ 7147ec681f3Smrg UNUSED struct v3d_context *v3d = v3d_context(pctx); 7159f464c52Smaya struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state); 7169f464c52Smaya 7179f464c52Smaya if (!so) 7189f464c52Smaya return NULL; 7199f464c52Smaya 7209f464c52Smaya memcpy(so, cso, sizeof(*cso)); 7219f464c52Smaya 7227ec681f3Smrg enum V3DX(Wrap_Mode) wrap_s = translate_wrap(cso->wrap_s); 7237ec681f3Smrg enum V3DX(Wrap_Mode) wrap_t = translate_wrap(cso->wrap_t); 7247ec681f3Smrg enum V3DX(Wrap_Mode) wrap_r = translate_wrap(cso->wrap_r); 7259f464c52Smaya 7269f464c52Smaya bool uses_border_color = (wrap_s == V3D_WRAP_MODE_BORDER || 7279f464c52Smaya wrap_t == V3D_WRAP_MODE_BORDER || 7289f464c52Smaya wrap_r == V3D_WRAP_MODE_BORDER); 7299f464c52Smaya so->border_color_variants = (uses_border_color && 7309f464c52Smaya (cso->border_color.ui[0] != 0 || 7319f464c52Smaya cso->border_color.ui[1] != 0 || 7329f464c52Smaya cso->border_color.ui[2] != 0 || 7339f464c52Smaya cso->border_color.ui[3] != 0)); 7349f464c52Smaya 7359f464c52Smaya#if V3D_VERSION >= 40 7369f464c52Smaya void *map; 7379f464c52Smaya int sampler_align = so->border_color_variants ? 32 : 8; 7389f464c52Smaya int sampler_size = align(cl_packet_length(SAMPLER_STATE), sampler_align); 7399f464c52Smaya int num_variants = (so->border_color_variants ? ARRAY_SIZE(so->sampler_state_offset) : 1); 7409f464c52Smaya u_upload_alloc(v3d->state_uploader, 0, 7419f464c52Smaya sampler_size * num_variants, 7429f464c52Smaya sampler_align, 7439f464c52Smaya &so->sampler_state_offset[0], 7449f464c52Smaya &so->sampler_state, 7459f464c52Smaya &map); 7469f464c52Smaya 7479f464c52Smaya for (int i = 0; i < num_variants; i++) { 7489f464c52Smaya so->sampler_state_offset[i] = 7499f464c52Smaya so->sampler_state_offset[0] + i * sampler_size; 7509f464c52Smaya v3d_upload_sampler_state_variant(map + i * sampler_size, 7517ec681f3Smrg cso, i); 75201e04c3fSmrg } 75301e04c3fSmrg 75401e04c3fSmrg#else /* V3D_VERSION < 40 */ 75501e04c3fSmrg v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) { 7569f464c52Smaya p0.s_wrap_mode = wrap_s; 7579f464c52Smaya p0.t_wrap_mode = wrap_t; 7589f464c52Smaya p0.r_wrap_mode = wrap_r; 75901e04c3fSmrg } 76001e04c3fSmrg 76101e04c3fSmrg v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) { 76201e04c3fSmrg tex.depth_compare_function = cso->compare_func; 76301e04c3fSmrg tex.fixed_bias = cso->lod_bias; 76401e04c3fSmrg } 76501e04c3fSmrg#endif /* V3D_VERSION < 40 */ 76601e04c3fSmrg return so; 76701e04c3fSmrg} 76801e04c3fSmrg 76901e04c3fSmrgstatic void 77001e04c3fSmrgv3d_sampler_states_bind(struct pipe_context *pctx, 77101e04c3fSmrg enum pipe_shader_type shader, unsigned start, 77201e04c3fSmrg unsigned nr, void **hwcso) 77301e04c3fSmrg{ 77401e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 7759f464c52Smaya struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader]; 77601e04c3fSmrg 77701e04c3fSmrg assert(start == 0); 77801e04c3fSmrg unsigned i; 77901e04c3fSmrg unsigned new_nr = 0; 78001e04c3fSmrg 78101e04c3fSmrg for (i = 0; i < nr; i++) { 78201e04c3fSmrg if (hwcso[i]) 78301e04c3fSmrg new_nr = i + 1; 78401e04c3fSmrg stage_tex->samplers[i] = hwcso[i]; 78501e04c3fSmrg } 78601e04c3fSmrg 78701e04c3fSmrg for (; i < stage_tex->num_samplers; i++) { 78801e04c3fSmrg stage_tex->samplers[i] = NULL; 78901e04c3fSmrg } 79001e04c3fSmrg 79101e04c3fSmrg stage_tex->num_samplers = new_nr; 7927ec681f3Smrg 7937ec681f3Smrg v3d_flag_dirty_sampler_state(v3d, shader); 79401e04c3fSmrg} 79501e04c3fSmrg 79601e04c3fSmrgstatic void 79701e04c3fSmrgv3d_sampler_state_delete(struct pipe_context *pctx, 79801e04c3fSmrg void *hwcso) 79901e04c3fSmrg{ 80001e04c3fSmrg struct pipe_sampler_state *psampler = hwcso; 80101e04c3fSmrg struct v3d_sampler_state *sampler = v3d_sampler_state(psampler); 80201e04c3fSmrg 8039f464c52Smaya pipe_resource_reference(&sampler->sampler_state, NULL); 80401e04c3fSmrg free(psampler); 80501e04c3fSmrg} 80601e04c3fSmrg 80701e04c3fSmrg#if V3D_VERSION >= 40 80801e04c3fSmrgstatic uint32_t 80901e04c3fSmrgtranslate_swizzle(unsigned char pipe_swizzle) 81001e04c3fSmrg{ 81101e04c3fSmrg switch (pipe_swizzle) { 81201e04c3fSmrg case PIPE_SWIZZLE_0: 81301e04c3fSmrg return 0; 81401e04c3fSmrg case PIPE_SWIZZLE_1: 81501e04c3fSmrg return 1; 81601e04c3fSmrg case PIPE_SWIZZLE_X: 81701e04c3fSmrg case PIPE_SWIZZLE_Y: 81801e04c3fSmrg case PIPE_SWIZZLE_Z: 81901e04c3fSmrg case PIPE_SWIZZLE_W: 82001e04c3fSmrg return 2 + pipe_swizzle; 82101e04c3fSmrg default: 82201e04c3fSmrg unreachable("unknown swizzle"); 82301e04c3fSmrg } 82401e04c3fSmrg} 82501e04c3fSmrg#endif 82601e04c3fSmrg 8279f464c52Smayastatic void 8289f464c52Smayav3d_setup_texture_shader_state(struct V3DX(TEXTURE_SHADER_STATE) *tex, 8299f464c52Smaya struct pipe_resource *prsc, 8309f464c52Smaya int base_level, int last_level, 8319f464c52Smaya int first_layer, int last_layer) 8329f464c52Smaya{ 8339f464c52Smaya struct v3d_resource *rsc = v3d_resource(prsc); 8349f464c52Smaya int msaa_scale = prsc->nr_samples > 1 ? 2 : 1; 8359f464c52Smaya 8369f464c52Smaya tex->image_width = prsc->width0 * msaa_scale; 8379f464c52Smaya tex->image_height = prsc->height0 * msaa_scale; 8389f464c52Smaya 8399f464c52Smaya#if V3D_VERSION >= 40 8409f464c52Smaya /* On 4.x, the height of a 1D texture is redefined to be the 8419f464c52Smaya * upper 14 bits of the width (which is only usable with txf). 8429f464c52Smaya */ 8439f464c52Smaya if (prsc->target == PIPE_TEXTURE_1D || 8449f464c52Smaya prsc->target == PIPE_TEXTURE_1D_ARRAY) { 8459f464c52Smaya tex->image_height = tex->image_width >> 14; 8469f464c52Smaya } 8479f464c52Smaya 8489f464c52Smaya tex->image_width &= (1 << 14) - 1; 8499f464c52Smaya tex->image_height &= (1 << 14) - 1; 8509f464c52Smaya#endif 8519f464c52Smaya 8529f464c52Smaya if (prsc->target == PIPE_TEXTURE_3D) { 8539f464c52Smaya tex->image_depth = prsc->depth0; 8549f464c52Smaya } else { 8559f464c52Smaya tex->image_depth = (last_layer - first_layer) + 1; 8569f464c52Smaya } 8579f464c52Smaya 8589f464c52Smaya tex->base_level = base_level; 8599f464c52Smaya#if V3D_VERSION >= 40 8609f464c52Smaya tex->max_level = last_level; 8619f464c52Smaya /* Note that we don't have a job to reference the texture's sBO 8629f464c52Smaya * at state create time, so any time this sampler view is used 8639f464c52Smaya * we need to add the texture to the job. 8649f464c52Smaya */ 8659f464c52Smaya tex->texture_base_pointer = 8669f464c52Smaya cl_address(NULL, 8679f464c52Smaya rsc->bo->offset + 8689f464c52Smaya v3d_layer_offset(prsc, 0, first_layer)); 8699f464c52Smaya#endif 8709f464c52Smaya tex->array_stride_64_byte_aligned = rsc->cube_map_stride / 64; 8719f464c52Smaya 8729f464c52Smaya /* Since other platform devices may produce UIF images even 8739f464c52Smaya * when they're not big enough for V3D to assume they're UIF, 8749f464c52Smaya * we force images with level 0 as UIF to be always treated 8759f464c52Smaya * that way. 8769f464c52Smaya */ 8779f464c52Smaya tex->level_0_is_strictly_uif = 8787ec681f3Smrg (rsc->slices[0].tiling == V3D_TILING_UIF_XOR || 8797ec681f3Smrg rsc->slices[0].tiling == V3D_TILING_UIF_NO_XOR); 8807ec681f3Smrg tex->level_0_xor_enable = (rsc->slices[0].tiling == V3D_TILING_UIF_XOR); 8819f464c52Smaya 8829f464c52Smaya if (tex->level_0_is_strictly_uif) 8839f464c52Smaya tex->level_0_ub_pad = rsc->slices[0].ub_pad; 8849f464c52Smaya 8859f464c52Smaya#if V3D_VERSION >= 40 8869f464c52Smaya if (tex->uif_xor_disable || 8879f464c52Smaya tex->level_0_is_strictly_uif) { 8889f464c52Smaya tex->extended = true; 8899f464c52Smaya } 8909f464c52Smaya#endif /* V3D_VERSION >= 40 */ 8919f464c52Smaya} 8929f464c52Smaya 8937ec681f3Smrgvoid 8947ec681f3Smrgv3dX(create_texture_shader_state_bo)(struct v3d_context *v3d, 8957ec681f3Smrg struct v3d_sampler_view *so) 8967ec681f3Smrg{ 8977ec681f3Smrg struct pipe_resource *prsc = so->texture; 8987ec681f3Smrg const struct pipe_sampler_view *cso = &so->base; 8997ec681f3Smrg struct v3d_screen *screen = v3d->screen; 9007ec681f3Smrg 9017ec681f3Smrg void *map; 9027ec681f3Smrg 9037ec681f3Smrg#if V3D_VERSION >= 40 9047ec681f3Smrg v3d_bo_unreference(&so->bo); 9057ec681f3Smrg so->bo = v3d_bo_alloc(v3d->screen, 9067ec681f3Smrg cl_packet_length(TEXTURE_SHADER_STATE), "sampler"); 9077ec681f3Smrg map = v3d_bo_map(so->bo); 9087ec681f3Smrg#else /* V3D_VERSION < 40 */ 9097ec681f3Smrg STATIC_ASSERT(sizeof(so->texture_shader_state) >= 9107ec681f3Smrg cl_packet_length(TEXTURE_SHADER_STATE)); 9117ec681f3Smrg map = &so->texture_shader_state; 9127ec681f3Smrg#endif 9137ec681f3Smrg 9147ec681f3Smrg v3dx_pack(map, TEXTURE_SHADER_STATE, tex) { 9157ec681f3Smrg v3d_setup_texture_shader_state(&tex, prsc, 9167ec681f3Smrg cso->u.tex.first_level, 9177ec681f3Smrg cso->u.tex.last_level, 9187ec681f3Smrg cso->u.tex.first_layer, 9197ec681f3Smrg cso->u.tex.last_layer); 9207ec681f3Smrg 9217ec681f3Smrg tex.srgb = util_format_is_srgb(cso->format); 9227ec681f3Smrg 9237ec681f3Smrg#if V3D_VERSION >= 40 9247ec681f3Smrg tex.swizzle_r = translate_swizzle(so->swizzle[0]); 9257ec681f3Smrg tex.swizzle_g = translate_swizzle(so->swizzle[1]); 9267ec681f3Smrg tex.swizzle_b = translate_swizzle(so->swizzle[2]); 9277ec681f3Smrg tex.swizzle_a = translate_swizzle(so->swizzle[3]); 9287ec681f3Smrg#endif 9297ec681f3Smrg 9307ec681f3Smrg if (prsc->nr_samples > 1 && V3D_VERSION < 40) { 9317ec681f3Smrg /* Using texture views to reinterpret formats on our 9327ec681f3Smrg * MSAA textures won't work, because we don't lay out 9337ec681f3Smrg * the bits in memory as it's expected -- for example, 9347ec681f3Smrg * RGBA8 and RGB10_A2 are compatible in the 9357ec681f3Smrg * ARB_texture_view spec, but in HW we lay them out as 9367ec681f3Smrg * 32bpp RGBA8 and 64bpp RGBA16F. Just assert for now 9377ec681f3Smrg * to catch failures. 9387ec681f3Smrg * 9397ec681f3Smrg * We explicitly allow remapping S8Z24 to RGBA8888 for 9407ec681f3Smrg * v3d_blit.c's stencil blits. 9417ec681f3Smrg */ 9427ec681f3Smrg assert((util_format_linear(cso->format) == 9437ec681f3Smrg util_format_linear(prsc->format)) || 9447ec681f3Smrg (prsc->format == PIPE_FORMAT_S8_UINT_Z24_UNORM && 9457ec681f3Smrg cso->format == PIPE_FORMAT_R8G8B8A8_UNORM)); 9467ec681f3Smrg uint32_t output_image_format = 9477ec681f3Smrg v3d_get_rt_format(&screen->devinfo, cso->format); 9487ec681f3Smrg uint32_t internal_type; 9497ec681f3Smrg uint32_t internal_bpp; 9507ec681f3Smrg v3d_get_internal_type_bpp_for_output_format(&screen->devinfo, 9517ec681f3Smrg output_image_format, 9527ec681f3Smrg &internal_type, 9537ec681f3Smrg &internal_bpp); 9547ec681f3Smrg 9557ec681f3Smrg switch (internal_type) { 9567ec681f3Smrg case V3D_INTERNAL_TYPE_8: 9577ec681f3Smrg tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8; 9587ec681f3Smrg break; 9597ec681f3Smrg case V3D_INTERNAL_TYPE_16F: 9607ec681f3Smrg tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F; 9617ec681f3Smrg break; 9627ec681f3Smrg default: 9637ec681f3Smrg unreachable("Bad MSAA texture type"); 9647ec681f3Smrg } 9657ec681f3Smrg 9667ec681f3Smrg /* sRGB was stored in the tile buffer as linear and 9677ec681f3Smrg * would have been encoded to sRGB on resolved tile 9687ec681f3Smrg * buffer store. Note that this means we would need 9697ec681f3Smrg * shader code if we wanted to read an MSAA sRGB 9707ec681f3Smrg * texture without sRGB decode. 9717ec681f3Smrg */ 9727ec681f3Smrg tex.srgb = false; 9737ec681f3Smrg } else { 9747ec681f3Smrg tex.texture_type = v3d_get_tex_format(&screen->devinfo, 9757ec681f3Smrg cso->format); 9767ec681f3Smrg } 9777ec681f3Smrg }; 9787ec681f3Smrg} 9797ec681f3Smrg 98001e04c3fSmrgstatic struct pipe_sampler_view * 98101e04c3fSmrgv3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, 98201e04c3fSmrg const struct pipe_sampler_view *cso) 98301e04c3fSmrg{ 98401e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 98501e04c3fSmrg struct v3d_screen *screen = v3d->screen; 98601e04c3fSmrg struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view); 98701e04c3fSmrg struct v3d_resource *rsc = v3d_resource(prsc); 98801e04c3fSmrg 98901e04c3fSmrg if (!so) 99001e04c3fSmrg return NULL; 99101e04c3fSmrg 99201e04c3fSmrg so->base = *cso; 99301e04c3fSmrg 99401e04c3fSmrg pipe_reference(NULL, &prsc->reference); 99501e04c3fSmrg 99601e04c3fSmrg /* Compute the sampler view's swizzle up front. This will be plugged 99701e04c3fSmrg * into either the sampler (for 16-bit returns) or the shader's 99801e04c3fSmrg * texture key (for 32) 99901e04c3fSmrg */ 100001e04c3fSmrg uint8_t view_swizzle[4] = { 100101e04c3fSmrg cso->swizzle_r, 100201e04c3fSmrg cso->swizzle_g, 100301e04c3fSmrg cso->swizzle_b, 100401e04c3fSmrg cso->swizzle_a 100501e04c3fSmrg }; 100601e04c3fSmrg const uint8_t *fmt_swizzle = 100701e04c3fSmrg v3d_get_format_swizzle(&screen->devinfo, so->base.format); 100801e04c3fSmrg util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle); 100901e04c3fSmrg 101001e04c3fSmrg so->base.texture = prsc; 101101e04c3fSmrg so->base.reference.count = 1; 101201e04c3fSmrg so->base.context = pctx; 101301e04c3fSmrg 10149f464c52Smaya if (rsc->separate_stencil && 10159f464c52Smaya cso->format == PIPE_FORMAT_X32_S8X24_UINT) { 10169f464c52Smaya rsc = rsc->separate_stencil; 10179f464c52Smaya prsc = &rsc->base; 10189f464c52Smaya } 10199f464c52Smaya 10209f464c52Smaya /* If we're sampling depth from depth/stencil, demote the format to 10219f464c52Smaya * just depth. u_format will end up giving the answers for the 10229f464c52Smaya * stencil channel, otherwise. 10239f464c52Smaya */ 10249f464c52Smaya enum pipe_format sample_format = cso->format; 10259f464c52Smaya if (sample_format == PIPE_FORMAT_S8_UINT_Z24_UNORM) 10269f464c52Smaya sample_format = PIPE_FORMAT_X8Z24_UNORM; 102701e04c3fSmrg 102801e04c3fSmrg#if V3D_VERSION >= 40 10299f464c52Smaya const struct util_format_description *desc = 10309f464c52Smaya util_format_description(sample_format); 10319f464c52Smaya 10329f464c52Smaya if (util_format_is_pure_integer(sample_format) && 10339f464c52Smaya !util_format_has_depth(desc)) { 10349f464c52Smaya int chan = util_format_get_first_non_void_channel(sample_format); 10359f464c52Smaya if (util_format_is_pure_uint(sample_format)) { 10369f464c52Smaya switch (desc->channel[chan].size) { 10379f464c52Smaya case 32: 10389f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_32; 10399f464c52Smaya break; 10409f464c52Smaya case 16: 10419f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_16U; 10429f464c52Smaya break; 10439f464c52Smaya case 10: 10449f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_1010102U; 10459f464c52Smaya break; 10469f464c52Smaya case 8: 10479f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_8U; 10489f464c52Smaya break; 10499f464c52Smaya } 10509f464c52Smaya } else { 10519f464c52Smaya switch (desc->channel[chan].size) { 10529f464c52Smaya case 32: 10539f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_32; 10549f464c52Smaya break; 10559f464c52Smaya case 16: 10569f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_16I; 10579f464c52Smaya break; 10589f464c52Smaya case 8: 10599f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_8I; 10609f464c52Smaya break; 10619f464c52Smaya } 10629f464c52Smaya } 10639f464c52Smaya } else { 10649f464c52Smaya if (v3d_get_tex_return_size(&screen->devinfo, sample_format, 10659f464c52Smaya PIPE_TEX_COMPARE_NONE) == 32) { 10669f464c52Smaya if (util_format_is_alpha(sample_format)) 10679f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_32_A; 10689f464c52Smaya else 10699f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_32; 10709f464c52Smaya } else { 10719f464c52Smaya if (util_format_is_luminance_alpha(sample_format)) 10729f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_F16_LA; 10739f464c52Smaya else if (util_format_is_alpha(sample_format)) 10749f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_F16_A; 10759f464c52Smaya else if (fmt_swizzle[0] == PIPE_SWIZZLE_Z) 10769f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_F16_BGRA; 10779f464c52Smaya else 10789f464c52Smaya so->sampler_variant = V3D_SAMPLER_STATE_F16; 107901e04c3fSmrg 10809f464c52Smaya } 108101e04c3fSmrg 10829f464c52Smaya if (util_format_is_unorm(sample_format)) { 10839f464c52Smaya so->sampler_variant += (V3D_SAMPLER_STATE_F16_UNORM - 10849f464c52Smaya V3D_SAMPLER_STATE_F16); 10859f464c52Smaya } else if (util_format_is_snorm(sample_format)){ 10869f464c52Smaya so->sampler_variant += (V3D_SAMPLER_STATE_F16_SNORM - 10879f464c52Smaya V3D_SAMPLER_STATE_F16); 10889f464c52Smaya } 10899f464c52Smaya } 10909f464c52Smaya#endif 109101e04c3fSmrg 10929f464c52Smaya /* V3D still doesn't support sampling from raster textures, so we will 10939f464c52Smaya * have to copy to a temporary tiled texture. 10949f464c52Smaya */ 10959f464c52Smaya if (!rsc->tiled && !(prsc->target == PIPE_TEXTURE_1D || 10969f464c52Smaya prsc->target == PIPE_TEXTURE_1D_ARRAY)) { 10979f464c52Smaya struct v3d_resource *shadow_parent = rsc; 10989f464c52Smaya struct pipe_resource tmpl = { 10999f464c52Smaya .target = prsc->target, 11009f464c52Smaya .format = prsc->format, 11019f464c52Smaya .width0 = u_minify(prsc->width0, 11029f464c52Smaya cso->u.tex.first_level), 11039f464c52Smaya .height0 = u_minify(prsc->height0, 11049f464c52Smaya cso->u.tex.first_level), 11059f464c52Smaya .depth0 = 1, 11069f464c52Smaya .array_size = 1, 11079f464c52Smaya .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 11089f464c52Smaya .last_level = cso->u.tex.last_level - cso->u.tex.first_level, 11099f464c52Smaya .nr_samples = prsc->nr_samples, 11109f464c52Smaya }; 11119f464c52Smaya 11129f464c52Smaya /* Create the shadow texture. The rest of the sampler view 11139f464c52Smaya * setup will use the shadow. 111401e04c3fSmrg */ 11159f464c52Smaya prsc = v3d_resource_create(pctx->screen, &tmpl); 11169f464c52Smaya if (!prsc) { 11179f464c52Smaya free(so); 11189f464c52Smaya return NULL; 111901e04c3fSmrg } 11209f464c52Smaya rsc = v3d_resource(prsc); 11219f464c52Smaya 11229f464c52Smaya /* Flag it as needing update of the contents from the parent. */ 11239f464c52Smaya rsc->writes = shadow_parent->writes - 1; 11249f464c52Smaya assert(rsc->tiled); 11259f464c52Smaya 11269f464c52Smaya so->texture = prsc; 11279f464c52Smaya } else { 11289f464c52Smaya pipe_resource_reference(&so->texture, prsc); 11299f464c52Smaya } 11309f464c52Smaya 11317ec681f3Smrg v3d_create_texture_shader_state_bo(v3d, so); 113201e04c3fSmrg 113301e04c3fSmrg return &so->base; 113401e04c3fSmrg} 113501e04c3fSmrg 113601e04c3fSmrgstatic void 113701e04c3fSmrgv3d_sampler_view_destroy(struct pipe_context *pctx, 113801e04c3fSmrg struct pipe_sampler_view *psview) 113901e04c3fSmrg{ 114001e04c3fSmrg struct v3d_sampler_view *sview = v3d_sampler_view(psview); 114101e04c3fSmrg 114201e04c3fSmrg v3d_bo_unreference(&sview->bo); 114301e04c3fSmrg pipe_resource_reference(&psview->texture, NULL); 11449f464c52Smaya pipe_resource_reference(&sview->texture, NULL); 114501e04c3fSmrg free(psview); 114601e04c3fSmrg} 114701e04c3fSmrg 114801e04c3fSmrgstatic void 114901e04c3fSmrgv3d_set_sampler_views(struct pipe_context *pctx, 115001e04c3fSmrg enum pipe_shader_type shader, 115101e04c3fSmrg unsigned start, unsigned nr, 11527ec681f3Smrg unsigned unbind_num_trailing_slots, 11537ec681f3Smrg bool take_ownership, 115401e04c3fSmrg struct pipe_sampler_view **views) 115501e04c3fSmrg{ 115601e04c3fSmrg struct v3d_context *v3d = v3d_context(pctx); 11579f464c52Smaya struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader]; 115801e04c3fSmrg unsigned i; 115901e04c3fSmrg unsigned new_nr = 0; 116001e04c3fSmrg 116101e04c3fSmrg assert(start == 0); 116201e04c3fSmrg 116301e04c3fSmrg for (i = 0; i < nr; i++) { 116401e04c3fSmrg if (views[i]) 116501e04c3fSmrg new_nr = i + 1; 11667ec681f3Smrg if (take_ownership) { 11677ec681f3Smrg pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 11687ec681f3Smrg stage_tex->textures[i] = views[i]; 11697ec681f3Smrg } else { 11707ec681f3Smrg pipe_sampler_view_reference(&stage_tex->textures[i], views[i]); 11717ec681f3Smrg } 117201e04c3fSmrg } 117301e04c3fSmrg 117401e04c3fSmrg for (; i < stage_tex->num_textures; i++) { 117501e04c3fSmrg pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 117601e04c3fSmrg } 117701e04c3fSmrg 117801e04c3fSmrg stage_tex->num_textures = new_nr; 11797ec681f3Smrg 11807ec681f3Smrg v3d_flag_dirty_sampler_state(v3d, shader); 118101e04c3fSmrg} 118201e04c3fSmrg 118301e04c3fSmrgstatic struct pipe_stream_output_target * 118401e04c3fSmrgv3d_create_stream_output_target(struct pipe_context *pctx, 118501e04c3fSmrg struct pipe_resource *prsc, 118601e04c3fSmrg unsigned buffer_offset, 118701e04c3fSmrg unsigned buffer_size) 118801e04c3fSmrg{ 11897ec681f3Smrg struct v3d_stream_output_target *target; 119001e04c3fSmrg 11917ec681f3Smrg target = CALLOC_STRUCT(v3d_stream_output_target); 119201e04c3fSmrg if (!target) 119301e04c3fSmrg return NULL; 119401e04c3fSmrg 11957ec681f3Smrg pipe_reference_init(&target->base.reference, 1); 11967ec681f3Smrg pipe_resource_reference(&target->base.buffer, prsc); 119701e04c3fSmrg 11987ec681f3Smrg target->base.context = pctx; 11997ec681f3Smrg target->base.buffer_offset = buffer_offset; 12007ec681f3Smrg target->base.buffer_size = buffer_size; 120101e04c3fSmrg 12027ec681f3Smrg return &target->base; 120301e04c3fSmrg} 120401e04c3fSmrg 120501e04c3fSmrgstatic void 120601e04c3fSmrgv3d_stream_output_target_destroy(struct pipe_context *pctx, 120701e04c3fSmrg struct pipe_stream_output_target *target) 120801e04c3fSmrg{ 120901e04c3fSmrg pipe_resource_reference(&target->buffer, NULL); 121001e04c3fSmrg free(target); 121101e04c3fSmrg} 121201e04c3fSmrg 121301e04c3fSmrgstatic void 121401e04c3fSmrgv3d_set_stream_output_targets(struct pipe_context *pctx, 121501e04c3fSmrg unsigned num_targets, 121601e04c3fSmrg struct pipe_stream_output_target **targets, 121701e04c3fSmrg const unsigned *offsets) 121801e04c3fSmrg{ 121901e04c3fSmrg struct v3d_context *ctx = v3d_context(pctx); 122001e04c3fSmrg struct v3d_streamout_stateobj *so = &ctx->streamout; 122101e04c3fSmrg unsigned i; 122201e04c3fSmrg 122301e04c3fSmrg assert(num_targets <= ARRAY_SIZE(so->targets)); 122401e04c3fSmrg 12257ec681f3Smrg /* Update recorded vertex counts when we are ending the recording of 12267ec681f3Smrg * transform feedback. We do this when we switch primitive types 12277ec681f3Smrg * at draw time, but if we haven't switched primitives in our last 12287ec681f3Smrg * draw we need to do it here as well. 12297ec681f3Smrg */ 12307ec681f3Smrg if (num_targets == 0 && so->num_targets > 0) 12317ec681f3Smrg v3d_update_primitive_counters(ctx); 12327ec681f3Smrg 123301e04c3fSmrg for (i = 0; i < num_targets; i++) { 123401e04c3fSmrg if (offsets[i] != -1) 123501e04c3fSmrg so->offsets[i] = offsets[i]; 123601e04c3fSmrg 123701e04c3fSmrg pipe_so_target_reference(&so->targets[i], targets[i]); 123801e04c3fSmrg } 123901e04c3fSmrg 124001e04c3fSmrg for (; i < so->num_targets; i++) 124101e04c3fSmrg pipe_so_target_reference(&so->targets[i], NULL); 124201e04c3fSmrg 124301e04c3fSmrg so->num_targets = num_targets; 124401e04c3fSmrg 12457ec681f3Smrg /* Create primitive counters BO if needed */ 12467ec681f3Smrg if (num_targets > 0) 12477ec681f3Smrg v3d_ensure_prim_counts_allocated(ctx); 12487ec681f3Smrg 12497ec681f3Smrg ctx->dirty |= V3D_DIRTY_STREAMOUT; 125001e04c3fSmrg} 125101e04c3fSmrg 12529f464c52Smayastatic void 12539f464c52Smayav3d_set_shader_buffers(struct pipe_context *pctx, 12549f464c52Smaya enum pipe_shader_type shader, 12559f464c52Smaya unsigned start, unsigned count, 12569f464c52Smaya const struct pipe_shader_buffer *buffers, 12579f464c52Smaya unsigned writable_bitmask) 12589f464c52Smaya{ 12599f464c52Smaya struct v3d_context *v3d = v3d_context(pctx); 12609f464c52Smaya struct v3d_ssbo_stateobj *so = &v3d->ssbo[shader]; 12619f464c52Smaya unsigned mask = 0; 12629f464c52Smaya 12639f464c52Smaya if (buffers) { 12649f464c52Smaya for (unsigned i = 0; i < count; i++) { 12659f464c52Smaya unsigned n = i + start; 12669f464c52Smaya struct pipe_shader_buffer *buf = &so->sb[n]; 12679f464c52Smaya 12689f464c52Smaya if ((buf->buffer == buffers[i].buffer) && 12699f464c52Smaya (buf->buffer_offset == buffers[i].buffer_offset) && 12709f464c52Smaya (buf->buffer_size == buffers[i].buffer_size)) 12719f464c52Smaya continue; 12729f464c52Smaya 12739f464c52Smaya mask |= 1 << n; 12749f464c52Smaya 12759f464c52Smaya buf->buffer_offset = buffers[i].buffer_offset; 12769f464c52Smaya buf->buffer_size = buffers[i].buffer_size; 12779f464c52Smaya pipe_resource_reference(&buf->buffer, buffers[i].buffer); 12789f464c52Smaya 12799f464c52Smaya if (buf->buffer) 12809f464c52Smaya so->enabled_mask |= 1 << n; 12819f464c52Smaya else 12829f464c52Smaya so->enabled_mask &= ~(1 << n); 12839f464c52Smaya } 12849f464c52Smaya } else { 12859f464c52Smaya mask = ((1 << count) - 1) << start; 12869f464c52Smaya 12879f464c52Smaya for (unsigned i = 0; i < count; i++) { 12889f464c52Smaya unsigned n = i + start; 12899f464c52Smaya struct pipe_shader_buffer *buf = &so->sb[n]; 12909f464c52Smaya 12919f464c52Smaya pipe_resource_reference(&buf->buffer, NULL); 12929f464c52Smaya } 12939f464c52Smaya 12949f464c52Smaya so->enabled_mask &= ~mask; 12959f464c52Smaya } 12969f464c52Smaya 12977ec681f3Smrg v3d->dirty |= V3D_DIRTY_SSBO; 12989f464c52Smaya} 12999f464c52Smaya 13009f464c52Smayastatic void 13019f464c52Smayav3d_create_image_view_texture_shader_state(struct v3d_context *v3d, 13029f464c52Smaya struct v3d_shaderimg_stateobj *so, 13039f464c52Smaya int img) 13049f464c52Smaya{ 13059f464c52Smaya#if V3D_VERSION >= 40 13069f464c52Smaya struct v3d_image_view *iview = &so->si[img]; 13079f464c52Smaya 13089f464c52Smaya void *map; 13099f464c52Smaya u_upload_alloc(v3d->uploader, 0, cl_packet_length(TEXTURE_SHADER_STATE), 13109f464c52Smaya 32, 13119f464c52Smaya &iview->tex_state_offset, 13129f464c52Smaya &iview->tex_state, 13139f464c52Smaya &map); 13149f464c52Smaya 13159f464c52Smaya struct pipe_resource *prsc = iview->base.resource; 13169f464c52Smaya 13179f464c52Smaya v3dx_pack(map, TEXTURE_SHADER_STATE, tex) { 13189f464c52Smaya v3d_setup_texture_shader_state(&tex, prsc, 13199f464c52Smaya iview->base.u.tex.level, 13209f464c52Smaya iview->base.u.tex.level, 13219f464c52Smaya iview->base.u.tex.first_layer, 13229f464c52Smaya iview->base.u.tex.last_layer); 13239f464c52Smaya 13249f464c52Smaya tex.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X); 13259f464c52Smaya tex.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y); 13269f464c52Smaya tex.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z); 13279f464c52Smaya tex.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W); 13289f464c52Smaya 13299f464c52Smaya tex.texture_type = v3d_get_tex_format(&v3d->screen->devinfo, 13309f464c52Smaya iview->base.format); 13319f464c52Smaya }; 13329f464c52Smaya#else /* V3D_VERSION < 40 */ 13339f464c52Smaya /* V3D 3.x doesn't use support shader image load/store operations on 13349f464c52Smaya * textures, so it would get lowered in the shader to general memory 13359f464c52Smaya * acceses. 13369f464c52Smaya */ 13379f464c52Smaya#endif 13389f464c52Smaya} 13399f464c52Smaya 13409f464c52Smayastatic void 13419f464c52Smayav3d_set_shader_images(struct pipe_context *pctx, 13429f464c52Smaya enum pipe_shader_type shader, 13439f464c52Smaya unsigned start, unsigned count, 13447ec681f3Smrg unsigned unbind_num_trailing_slots, 13459f464c52Smaya const struct pipe_image_view *images) 13469f464c52Smaya{ 13479f464c52Smaya struct v3d_context *v3d = v3d_context(pctx); 13489f464c52Smaya struct v3d_shaderimg_stateobj *so = &v3d->shaderimg[shader]; 13499f464c52Smaya 13509f464c52Smaya if (images) { 13519f464c52Smaya for (unsigned i = 0; i < count; i++) { 13529f464c52Smaya unsigned n = i + start; 13539f464c52Smaya struct v3d_image_view *iview = &so->si[n]; 13549f464c52Smaya 13559f464c52Smaya if ((iview->base.resource == images[i].resource) && 13569f464c52Smaya (iview->base.format == images[i].format) && 13579f464c52Smaya (iview->base.access == images[i].access) && 13589f464c52Smaya !memcmp(&iview->base.u, &images[i].u, 13599f464c52Smaya sizeof(iview->base.u))) 13609f464c52Smaya continue; 13619f464c52Smaya 13629f464c52Smaya util_copy_image_view(&iview->base, &images[i]); 13639f464c52Smaya 13649f464c52Smaya if (iview->base.resource) { 13659f464c52Smaya so->enabled_mask |= 1 << n; 13669f464c52Smaya v3d_create_image_view_texture_shader_state(v3d, 13679f464c52Smaya so, 13689f464c52Smaya n); 13699f464c52Smaya } else { 13709f464c52Smaya so->enabled_mask &= ~(1 << n); 13719f464c52Smaya pipe_resource_reference(&iview->tex_state, NULL); 13729f464c52Smaya } 13739f464c52Smaya } 13749f464c52Smaya } else { 13759f464c52Smaya for (unsigned i = 0; i < count; i++) { 13769f464c52Smaya unsigned n = i + start; 13779f464c52Smaya struct v3d_image_view *iview = &so->si[n]; 13789f464c52Smaya 13799f464c52Smaya pipe_resource_reference(&iview->base.resource, NULL); 13809f464c52Smaya pipe_resource_reference(&iview->tex_state, NULL); 13819f464c52Smaya } 13829f464c52Smaya 13839f464c52Smaya if (count == 32) 13849f464c52Smaya so->enabled_mask = 0; 13859f464c52Smaya else 13869f464c52Smaya so->enabled_mask &= ~(((1 << count) - 1) << start); 13879f464c52Smaya } 13889f464c52Smaya 13897ec681f3Smrg v3d->dirty |= V3D_DIRTY_SHADER_IMAGE; 13907ec681f3Smrg 13917ec681f3Smrg if (unbind_num_trailing_slots) { 13927ec681f3Smrg v3d_set_shader_images(pctx, shader, start + count, 13937ec681f3Smrg unbind_num_trailing_slots, 0, NULL); 13947ec681f3Smrg } 13959f464c52Smaya} 13969f464c52Smaya 139701e04c3fSmrgvoid 139801e04c3fSmrgv3dX(state_init)(struct pipe_context *pctx) 139901e04c3fSmrg{ 140001e04c3fSmrg pctx->set_blend_color = v3d_set_blend_color; 140101e04c3fSmrg pctx->set_stencil_ref = v3d_set_stencil_ref; 140201e04c3fSmrg pctx->set_clip_state = v3d_set_clip_state; 140301e04c3fSmrg pctx->set_sample_mask = v3d_set_sample_mask; 140401e04c3fSmrg pctx->set_constant_buffer = v3d_set_constant_buffer; 140501e04c3fSmrg pctx->set_framebuffer_state = v3d_set_framebuffer_state; 140601e04c3fSmrg pctx->set_polygon_stipple = v3d_set_polygon_stipple; 140701e04c3fSmrg pctx->set_scissor_states = v3d_set_scissor_states; 140801e04c3fSmrg pctx->set_viewport_states = v3d_set_viewport_states; 140901e04c3fSmrg 141001e04c3fSmrg pctx->set_vertex_buffers = v3d_set_vertex_buffers; 141101e04c3fSmrg 141201e04c3fSmrg pctx->create_blend_state = v3d_create_blend_state; 141301e04c3fSmrg pctx->bind_blend_state = v3d_blend_state_bind; 141401e04c3fSmrg pctx->delete_blend_state = v3d_generic_cso_state_delete; 141501e04c3fSmrg 141601e04c3fSmrg pctx->create_rasterizer_state = v3d_create_rasterizer_state; 141701e04c3fSmrg pctx->bind_rasterizer_state = v3d_rasterizer_state_bind; 141801e04c3fSmrg pctx->delete_rasterizer_state = v3d_generic_cso_state_delete; 141901e04c3fSmrg 142001e04c3fSmrg pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state; 142101e04c3fSmrg pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind; 142201e04c3fSmrg pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete; 142301e04c3fSmrg 142401e04c3fSmrg pctx->create_vertex_elements_state = v3d_vertex_state_create; 142501e04c3fSmrg pctx->delete_vertex_elements_state = v3d_vertex_state_delete; 142601e04c3fSmrg pctx->bind_vertex_elements_state = v3d_vertex_state_bind; 142701e04c3fSmrg 142801e04c3fSmrg pctx->create_sampler_state = v3d_create_sampler_state; 142901e04c3fSmrg pctx->delete_sampler_state = v3d_sampler_state_delete; 143001e04c3fSmrg pctx->bind_sampler_states = v3d_sampler_states_bind; 143101e04c3fSmrg 143201e04c3fSmrg pctx->create_sampler_view = v3d_create_sampler_view; 143301e04c3fSmrg pctx->sampler_view_destroy = v3d_sampler_view_destroy; 143401e04c3fSmrg pctx->set_sampler_views = v3d_set_sampler_views; 143501e04c3fSmrg 14369f464c52Smaya pctx->set_shader_buffers = v3d_set_shader_buffers; 14379f464c52Smaya pctx->set_shader_images = v3d_set_shader_images; 14389f464c52Smaya 143901e04c3fSmrg pctx->create_stream_output_target = v3d_create_stream_output_target; 144001e04c3fSmrg pctx->stream_output_target_destroy = v3d_stream_output_target_destroy; 144101e04c3fSmrg pctx->set_stream_output_targets = v3d_set_stream_output_targets; 144201e04c3fSmrg} 1443