v3dx_state.c revision 01e04c3f
1/* 2 * Copyright © 2014-2017 Broadcom 3 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#include "pipe/p_state.h" 26#include "util/u_format.h" 27#include "util/u_framebuffer.h" 28#include "util/u_inlines.h" 29#include "util/u_math.h" 30#include "util/u_memory.h" 31#include "util/u_half.h" 32#include "util/u_helpers.h" 33 34#include "v3d_context.h" 35#include "v3d_tiling.h" 36#include "broadcom/common/v3d_macros.h" 37#include "broadcom/cle/v3dx_pack.h" 38 39static void 40v3d_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso) 41{ 42 free(hwcso); 43} 44 45static void 46v3d_set_blend_color(struct pipe_context *pctx, 47 const struct pipe_blend_color *blend_color) 48{ 49 struct v3d_context *v3d = v3d_context(pctx); 50 v3d->blend_color.f = *blend_color; 51 for (int i = 0; i < 4; i++) { 52 v3d->blend_color.hf[i] = 53 util_float_to_half(blend_color->color[i]); 54 } 55 v3d->dirty |= VC5_DIRTY_BLEND_COLOR; 56} 57 58static void 59v3d_set_stencil_ref(struct pipe_context *pctx, 60 const struct pipe_stencil_ref *stencil_ref) 61{ 62 struct v3d_context *v3d = v3d_context(pctx); 63 v3d->stencil_ref = *stencil_ref; 64 v3d->dirty |= VC5_DIRTY_STENCIL_REF; 65} 66 67static void 68v3d_set_clip_state(struct pipe_context *pctx, 69 const struct pipe_clip_state *clip) 70{ 71 struct v3d_context *v3d = v3d_context(pctx); 72 v3d->clip = *clip; 73 v3d->dirty |= VC5_DIRTY_CLIP; 74} 75 76static void 77v3d_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 78{ 79 struct v3d_context *v3d = v3d_context(pctx); 80 v3d->sample_mask = sample_mask & ((1 << VC5_MAX_SAMPLES) - 1); 81 v3d->dirty |= VC5_DIRTY_SAMPLE_STATE; 82} 83 84static void * 85v3d_create_rasterizer_state(struct pipe_context *pctx, 86 const struct pipe_rasterizer_state *cso) 87{ 88 struct v3d_rasterizer_state *so; 89 90 so = CALLOC_STRUCT(v3d_rasterizer_state); 91 if (!so) 92 return NULL; 93 94 so->base = *cso; 95 96 /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835, 97 * BCM21553). 98 */ 99 so->point_size = MAX2(cso->point_size, .125f); 100 101 STATIC_ASSERT(sizeof(so->depth_offset) >= 102 cl_packet_length(DEPTH_OFFSET)); 103 v3dx_pack(&so->depth_offset, DEPTH_OFFSET, depth) { 104 depth.depth_offset_factor = cso->offset_scale; 105 depth.depth_offset_units = cso->offset_units; 106 } 107 108 /* The HW treats polygon offset units based on a Z24 buffer, so we 109 * need to scale up offset_units if we're only Z16. 110 */ 111 v3dx_pack(&so->depth_offset_z16, DEPTH_OFFSET, depth) { 112 depth.depth_offset_factor = cso->offset_scale; 113 depth.depth_offset_units = cso->offset_units * 256.0; 114 } 115 116 return so; 117} 118 119/* Blend state is baked into shaders. */ 120static void * 121v3d_create_blend_state(struct pipe_context *pctx, 122 const struct pipe_blend_state *cso) 123{ 124 struct v3d_blend_state *so; 125 126 so = CALLOC_STRUCT(v3d_blend_state); 127 if (!so) 128 return NULL; 129 130 so->base = *cso; 131 132 if (cso->independent_blend_enable) { 133 for (int i = 0; i < VC5_MAX_DRAW_BUFFERS; i++) { 134 so->blend_enables |= cso->rt[i].blend_enable << i; 135 136 /* V3D 4.x is when we got independent blend enables. */ 137 assert(V3D_VERSION >= 40 || 138 cso->rt[i].blend_enable == cso->rt[0].blend_enable); 139 } 140 } else { 141 if (cso->rt[0].blend_enable) 142 so->blend_enables = (1 << VC5_MAX_DRAW_BUFFERS) - 1; 143 } 144 145 return so; 146} 147 148static uint32_t 149translate_stencil_op(enum pipe_stencil_op op) 150{ 151 switch (op) { 152 case PIPE_STENCIL_OP_KEEP: return V3D_STENCIL_OP_KEEP; 153 case PIPE_STENCIL_OP_ZERO: return V3D_STENCIL_OP_ZERO; 154 case PIPE_STENCIL_OP_REPLACE: return V3D_STENCIL_OP_REPLACE; 155 case PIPE_STENCIL_OP_INCR: return V3D_STENCIL_OP_INCR; 156 case PIPE_STENCIL_OP_DECR: return V3D_STENCIL_OP_DECR; 157 case PIPE_STENCIL_OP_INCR_WRAP: return V3D_STENCIL_OP_INCWRAP; 158 case PIPE_STENCIL_OP_DECR_WRAP: return V3D_STENCIL_OP_DECWRAP; 159 case PIPE_STENCIL_OP_INVERT: return V3D_STENCIL_OP_INVERT; 160 } 161 unreachable("bad stencil op"); 162} 163 164static void * 165v3d_create_depth_stencil_alpha_state(struct pipe_context *pctx, 166 const struct pipe_depth_stencil_alpha_state *cso) 167{ 168 struct v3d_depth_stencil_alpha_state *so; 169 170 so = CALLOC_STRUCT(v3d_depth_stencil_alpha_state); 171 if (!so) 172 return NULL; 173 174 so->base = *cso; 175 176 if (cso->depth.enabled) { 177 switch (cso->depth.func) { 178 case PIPE_FUNC_LESS: 179 case PIPE_FUNC_LEQUAL: 180 so->ez_state = VC5_EZ_LT_LE; 181 break; 182 case PIPE_FUNC_GREATER: 183 case PIPE_FUNC_GEQUAL: 184 so->ez_state = VC5_EZ_GT_GE; 185 break; 186 case PIPE_FUNC_NEVER: 187 case PIPE_FUNC_EQUAL: 188 so->ez_state = VC5_EZ_UNDECIDED; 189 break; 190 default: 191 so->ez_state = VC5_EZ_DISABLED; 192 break; 193 } 194 195 /* If stencil is enabled and it's not a no-op, then it would 196 * break EZ updates. 197 */ 198 if (cso->stencil[0].enabled && 199 (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP || 200 cso->stencil[0].func != PIPE_FUNC_ALWAYS || 201 (cso->stencil[1].enabled && 202 (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP && 203 cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) { 204 so->ez_state = VC5_EZ_DISABLED; 205 } 206 } 207 208 const struct pipe_stencil_state *front = &cso->stencil[0]; 209 const struct pipe_stencil_state *back = &cso->stencil[1]; 210 211 if (front->enabled) { 212 STATIC_ASSERT(sizeof(so->stencil_front) >= 213 cl_packet_length(STENCIL_CFG)); 214 v3dx_pack(&so->stencil_front, STENCIL_CFG, config) { 215 config.front_config = true; 216 /* If !back->enabled, then the front values should be 217 * used for both front and back-facing primitives. 218 */ 219 config.back_config = !back->enabled; 220 221 config.stencil_write_mask = front->writemask; 222 config.stencil_test_mask = front->valuemask; 223 224 config.stencil_test_function = front->func; 225 config.stencil_pass_op = 226 translate_stencil_op(front->zpass_op); 227 config.depth_test_fail_op = 228 translate_stencil_op(front->zfail_op); 229 config.stencil_test_fail_op = 230 translate_stencil_op(front->fail_op); 231 } 232 } 233 if (back->enabled) { 234 STATIC_ASSERT(sizeof(so->stencil_back) >= 235 cl_packet_length(STENCIL_CFG)); 236 v3dx_pack(&so->stencil_back, STENCIL_CFG, config) { 237 config.front_config = false; 238 config.back_config = true; 239 240 config.stencil_write_mask = back->writemask; 241 config.stencil_test_mask = back->valuemask; 242 243 config.stencil_test_function = back->func; 244 config.stencil_pass_op = 245 translate_stencil_op(back->zpass_op); 246 config.depth_test_fail_op = 247 translate_stencil_op(back->zfail_op); 248 config.stencil_test_fail_op = 249 translate_stencil_op(back->fail_op); 250 } 251 } 252 253 return so; 254} 255 256static void 257v3d_set_polygon_stipple(struct pipe_context *pctx, 258 const struct pipe_poly_stipple *stipple) 259{ 260 struct v3d_context *v3d = v3d_context(pctx); 261 v3d->stipple = *stipple; 262 v3d->dirty |= VC5_DIRTY_STIPPLE; 263} 264 265static void 266v3d_set_scissor_states(struct pipe_context *pctx, 267 unsigned start_slot, 268 unsigned num_scissors, 269 const struct pipe_scissor_state *scissor) 270{ 271 struct v3d_context *v3d = v3d_context(pctx); 272 273 v3d->scissor = *scissor; 274 v3d->dirty |= VC5_DIRTY_SCISSOR; 275} 276 277static void 278v3d_set_viewport_states(struct pipe_context *pctx, 279 unsigned start_slot, 280 unsigned num_viewports, 281 const struct pipe_viewport_state *viewport) 282{ 283 struct v3d_context *v3d = v3d_context(pctx); 284 v3d->viewport = *viewport; 285 v3d->dirty |= VC5_DIRTY_VIEWPORT; 286} 287 288static void 289v3d_set_vertex_buffers(struct pipe_context *pctx, 290 unsigned start_slot, unsigned count, 291 const struct pipe_vertex_buffer *vb) 292{ 293 struct v3d_context *v3d = v3d_context(pctx); 294 struct v3d_vertexbuf_stateobj *so = &v3d->vertexbuf; 295 296 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, 297 start_slot, count); 298 so->count = util_last_bit(so->enabled_mask); 299 300 v3d->dirty |= VC5_DIRTY_VTXBUF; 301} 302 303static void 304v3d_blend_state_bind(struct pipe_context *pctx, void *hwcso) 305{ 306 struct v3d_context *v3d = v3d_context(pctx); 307 v3d->blend = hwcso; 308 v3d->dirty |= VC5_DIRTY_BLEND; 309} 310 311static void 312v3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) 313{ 314 struct v3d_context *v3d = v3d_context(pctx); 315 v3d->rasterizer = hwcso; 316 v3d->dirty |= VC5_DIRTY_RASTERIZER; 317} 318 319static void 320v3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso) 321{ 322 struct v3d_context *v3d = v3d_context(pctx); 323 v3d->zsa = hwcso; 324 v3d->dirty |= VC5_DIRTY_ZSA; 325} 326 327static void * 328v3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements, 329 const struct pipe_vertex_element *elements) 330{ 331 struct v3d_context *v3d = v3d_context(pctx); 332 struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj); 333 334 if (!so) 335 return NULL; 336 337 memcpy(so->pipe, elements, sizeof(*elements) * num_elements); 338 so->num_elements = num_elements; 339 340 for (int i = 0; i < so->num_elements; i++) { 341 const struct pipe_vertex_element *elem = &elements[i]; 342 const struct util_format_description *desc = 343 util_format_description(elem->src_format); 344 uint32_t r_size = desc->channel[0].size; 345 346 const uint32_t size = 347 cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD); 348 349 v3dx_pack(&so->attrs[i * size], 350 GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) { 351 /* vec_size == 0 means 4 */ 352 attr.vec_size = desc->nr_channels & 3; 353 attr.signed_int_type = (desc->channel[0].type == 354 UTIL_FORMAT_TYPE_SIGNED); 355 356 attr.normalized_int_type = desc->channel[0].normalized; 357 attr.read_as_int_uint = desc->channel[0].pure_integer; 358 attr.instance_divisor = MIN2(elem->instance_divisor, 359 0xffff); 360 361 switch (desc->channel[0].type) { 362 case UTIL_FORMAT_TYPE_FLOAT: 363 if (r_size == 32) { 364 attr.type = ATTRIBUTE_FLOAT; 365 } else { 366 assert(r_size == 16); 367 attr.type = ATTRIBUTE_HALF_FLOAT; 368 } 369 break; 370 371 case UTIL_FORMAT_TYPE_SIGNED: 372 case UTIL_FORMAT_TYPE_UNSIGNED: 373 switch (r_size) { 374 case 32: 375 attr.type = ATTRIBUTE_INT; 376 break; 377 case 16: 378 attr.type = ATTRIBUTE_SHORT; 379 break; 380 case 10: 381 attr.type = ATTRIBUTE_INT2_10_10_10; 382 break; 383 case 8: 384 attr.type = ATTRIBUTE_BYTE; 385 break; 386 default: 387 fprintf(stderr, 388 "format %s unsupported\n", 389 desc->name); 390 attr.type = ATTRIBUTE_BYTE; 391 abort(); 392 } 393 break; 394 395 default: 396 fprintf(stderr, 397 "format %s unsupported\n", 398 desc->name); 399 abort(); 400 } 401 } 402 } 403 404 /* Set up the default attribute values in case any of the vertex 405 * elements use them. 406 */ 407 so->default_attribute_values = v3d_bo_alloc(v3d->screen, 408 VC5_MAX_ATTRIBUTES * 409 4 * sizeof(float), 410 "default_attributes"); 411 uint32_t *attrs = v3d_bo_map(so->default_attribute_values); 412 for (int i = 0; i < VC5_MAX_ATTRIBUTES; i++) { 413 attrs[i * 4 + 0] = 0; 414 attrs[i * 4 + 1] = 0; 415 attrs[i * 4 + 2] = 0; 416 if (i < so->num_elements && 417 util_format_is_pure_integer(so->pipe[i].src_format)) { 418 attrs[i * 4 + 3] = 1; 419 } else { 420 attrs[i * 4 + 3] = fui(1.0); 421 } 422 } 423 424 return so; 425} 426 427static void 428v3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso) 429{ 430 struct v3d_vertex_stateobj *so = hwcso; 431 432 v3d_bo_unreference(&so->default_attribute_values); 433 free(so); 434} 435 436static void 437v3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso) 438{ 439 struct v3d_context *v3d = v3d_context(pctx); 440 v3d->vtx = hwcso; 441 v3d->dirty |= VC5_DIRTY_VTXSTATE; 442} 443 444static void 445v3d_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index, 446 const struct pipe_constant_buffer *cb) 447{ 448 struct v3d_context *v3d = v3d_context(pctx); 449 struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader]; 450 451 util_copy_constant_buffer(&so->cb[index], cb); 452 453 /* Note that the state tracker can unbind constant buffers by 454 * passing NULL here. 455 */ 456 if (unlikely(!cb)) { 457 so->enabled_mask &= ~(1 << index); 458 so->dirty_mask &= ~(1 << index); 459 return; 460 } 461 462 so->enabled_mask |= 1 << index; 463 so->dirty_mask |= 1 << index; 464 v3d->dirty |= VC5_DIRTY_CONSTBUF; 465} 466 467static void 468v3d_set_framebuffer_state(struct pipe_context *pctx, 469 const struct pipe_framebuffer_state *framebuffer) 470{ 471 struct v3d_context *v3d = v3d_context(pctx); 472 struct pipe_framebuffer_state *cso = &v3d->framebuffer; 473 474 v3d->job = NULL; 475 476 util_copy_framebuffer_state(cso, framebuffer); 477 478 v3d->swap_color_rb = 0; 479 v3d->blend_dst_alpha_one = 0; 480 for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) { 481 struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i]; 482 if (!cbuf) 483 continue; 484 485 const struct util_format_description *desc = 486 util_format_description(cbuf->format); 487 488 /* For BGRA8 formats (DRI window system default format), we 489 * need to swap R and B, since the HW's format is RGBA8. 490 */ 491 if (desc->swizzle[0] == PIPE_SWIZZLE_Z && 492 cbuf->format != PIPE_FORMAT_B5G6R5_UNORM) { 493 v3d->swap_color_rb |= 1 << i; 494 } 495 496 if (desc->swizzle[3] == PIPE_SWIZZLE_1) 497 v3d->blend_dst_alpha_one |= 1 << i; 498 } 499 500 v3d->dirty |= VC5_DIRTY_FRAMEBUFFER; 501} 502 503static struct v3d_texture_stateobj * 504v3d_get_stage_tex(struct v3d_context *v3d, enum pipe_shader_type shader) 505{ 506 switch (shader) { 507 case PIPE_SHADER_FRAGMENT: 508 v3d->dirty |= VC5_DIRTY_FRAGTEX; 509 return &v3d->fragtex; 510 break; 511 case PIPE_SHADER_VERTEX: 512 v3d->dirty |= VC5_DIRTY_VERTTEX; 513 return &v3d->verttex; 514 break; 515 default: 516 fprintf(stderr, "Unknown shader target %d\n", shader); 517 abort(); 518 } 519} 520 521static uint32_t translate_wrap(uint32_t pipe_wrap, bool using_nearest) 522{ 523 switch (pipe_wrap) { 524 case PIPE_TEX_WRAP_REPEAT: 525 return 0; 526 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 527 return 1; 528 case PIPE_TEX_WRAP_MIRROR_REPEAT: 529 return 2; 530 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 531 return 3; 532 case PIPE_TEX_WRAP_CLAMP: 533 return (using_nearest ? 1 : 3); 534 default: 535 unreachable("Unknown wrap mode"); 536 } 537} 538 539 540static void * 541v3d_create_sampler_state(struct pipe_context *pctx, 542 const struct pipe_sampler_state *cso) 543{ 544 MAYBE_UNUSED struct v3d_context *v3d = v3d_context(pctx); 545 struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state); 546 547 if (!so) 548 return NULL; 549 550 memcpy(so, cso, sizeof(*cso)); 551 552 bool either_nearest = 553 (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST || 554 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST); 555 556#if V3D_VERSION >= 40 557 so->bo = v3d_bo_alloc(v3d->screen, cl_packet_length(SAMPLER_STATE), 558 "sampler"); 559 void *map = v3d_bo_map(so->bo); 560 561 v3dx_pack(map, SAMPLER_STATE, sampler) { 562 sampler.wrap_i_border = false; 563 564 sampler.wrap_s = translate_wrap(cso->wrap_s, either_nearest); 565 sampler.wrap_t = translate_wrap(cso->wrap_t, either_nearest); 566 sampler.wrap_r = translate_wrap(cso->wrap_r, either_nearest); 567 568 sampler.fixed_bias = cso->lod_bias; 569 sampler.depth_compare_function = cso->compare_func; 570 571 sampler.min_filter_nearest = 572 cso->min_img_filter == PIPE_TEX_FILTER_NEAREST; 573 sampler.mag_filter_nearest = 574 cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST; 575 sampler.mip_filter_nearest = 576 cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR; 577 578 sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod), 579 15); 580 sampler.max_level_of_detail = MIN2(cso->max_lod, 15); 581 582 /* If we're not doing inter-miplevel filtering, we need to 583 * clamp the LOD so that we only sample from baselevel. 584 * However, we need to still allow the calculated LOD to be 585 * fractionally over the baselevel, so that the HW can decide 586 * between the min and mag filters. 587 */ 588 if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 589 sampler.min_level_of_detail = 590 MIN2(sampler.min_level_of_detail, 1.0 / 256.0); 591 sampler.max_level_of_detail = 592 MIN2(sampler.max_level_of_detail, 1.0 / 256.0); 593 } 594 595 if (cso->max_anisotropy) { 596 sampler.anisotropy_enable = true; 597 598 if (cso->max_anisotropy > 8) 599 sampler.maximum_anisotropy = 3; 600 else if (cso->max_anisotropy > 4) 601 sampler.maximum_anisotropy = 2; 602 else if (cso->max_anisotropy > 2) 603 sampler.maximum_anisotropy = 1; 604 } 605 606 sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS; 607 /* XXX: The border color field is in the TMU blending format 608 * (32, f16, or i16), and we need to customize it based on 609 * that. 610 * 611 * XXX: for compat alpha formats, we need the alpha field to 612 * be in the red channel. 613 */ 614 sampler.border_color_red = 615 util_float_to_half(cso->border_color.f[0]); 616 sampler.border_color_green = 617 util_float_to_half(cso->border_color.f[1]); 618 sampler.border_color_blue = 619 util_float_to_half(cso->border_color.f[2]); 620 sampler.border_color_alpha = 621 util_float_to_half(cso->border_color.f[3]); 622 } 623 624#else /* V3D_VERSION < 40 */ 625 v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) { 626 p0.s_wrap_mode = translate_wrap(cso->wrap_s, either_nearest); 627 p0.t_wrap_mode = translate_wrap(cso->wrap_t, either_nearest); 628 p0.r_wrap_mode = translate_wrap(cso->wrap_r, either_nearest); 629 } 630 631 v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) { 632 tex.depth_compare_function = cso->compare_func; 633 tex.fixed_bias = cso->lod_bias; 634 } 635#endif /* V3D_VERSION < 40 */ 636 return so; 637} 638 639static void 640v3d_sampler_states_bind(struct pipe_context *pctx, 641 enum pipe_shader_type shader, unsigned start, 642 unsigned nr, void **hwcso) 643{ 644 struct v3d_context *v3d = v3d_context(pctx); 645 struct v3d_texture_stateobj *stage_tex = v3d_get_stage_tex(v3d, shader); 646 647 assert(start == 0); 648 unsigned i; 649 unsigned new_nr = 0; 650 651 for (i = 0; i < nr; i++) { 652 if (hwcso[i]) 653 new_nr = i + 1; 654 stage_tex->samplers[i] = hwcso[i]; 655 } 656 657 for (; i < stage_tex->num_samplers; i++) { 658 stage_tex->samplers[i] = NULL; 659 } 660 661 stage_tex->num_samplers = new_nr; 662} 663 664static void 665v3d_sampler_state_delete(struct pipe_context *pctx, 666 void *hwcso) 667{ 668 struct pipe_sampler_state *psampler = hwcso; 669 struct v3d_sampler_state *sampler = v3d_sampler_state(psampler); 670 671 v3d_bo_unreference(&sampler->bo); 672 free(psampler); 673} 674 675#if V3D_VERSION >= 40 676static uint32_t 677translate_swizzle(unsigned char pipe_swizzle) 678{ 679 switch (pipe_swizzle) { 680 case PIPE_SWIZZLE_0: 681 return 0; 682 case PIPE_SWIZZLE_1: 683 return 1; 684 case PIPE_SWIZZLE_X: 685 case PIPE_SWIZZLE_Y: 686 case PIPE_SWIZZLE_Z: 687 case PIPE_SWIZZLE_W: 688 return 2 + pipe_swizzle; 689 default: 690 unreachable("unknown swizzle"); 691 } 692} 693#endif 694 695static struct pipe_sampler_view * 696v3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, 697 const struct pipe_sampler_view *cso) 698{ 699 struct v3d_context *v3d = v3d_context(pctx); 700 struct v3d_screen *screen = v3d->screen; 701 struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view); 702 struct v3d_resource *rsc = v3d_resource(prsc); 703 704 if (!so) 705 return NULL; 706 707 so->base = *cso; 708 709 pipe_reference(NULL, &prsc->reference); 710 711 /* Compute the sampler view's swizzle up front. This will be plugged 712 * into either the sampler (for 16-bit returns) or the shader's 713 * texture key (for 32) 714 */ 715 uint8_t view_swizzle[4] = { 716 cso->swizzle_r, 717 cso->swizzle_g, 718 cso->swizzle_b, 719 cso->swizzle_a 720 }; 721 const uint8_t *fmt_swizzle = 722 v3d_get_format_swizzle(&screen->devinfo, so->base.format); 723 util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle); 724 725 so->base.texture = prsc; 726 so->base.reference.count = 1; 727 so->base.context = pctx; 728 729 int msaa_scale = prsc->nr_samples > 1 ? 2 : 1; 730 731#if V3D_VERSION >= 40 732 so->bo = v3d_bo_alloc(v3d->screen, 733 cl_packet_length(TEXTURE_SHADER_STATE), "sampler"); 734 void *map = v3d_bo_map(so->bo); 735 736 v3dx_pack(map, TEXTURE_SHADER_STATE, tex) { 737#else /* V3D_VERSION < 40 */ 738 STATIC_ASSERT(sizeof(so->texture_shader_state) >= 739 cl_packet_length(TEXTURE_SHADER_STATE)); 740 v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) { 741#endif 742 743 tex.image_width = prsc->width0 * msaa_scale; 744 tex.image_height = prsc->height0 * msaa_scale; 745 746#if V3D_VERSION >= 40 747 /* On 4.x, the height of a 1D texture is redefined to be the 748 * upper 14 bits of the width (which is only usable with txf). 749 */ 750 if (prsc->target == PIPE_TEXTURE_1D || 751 prsc->target == PIPE_TEXTURE_1D_ARRAY) { 752 tex.image_height = tex.image_width >> 14; 753 } 754#endif 755 756 if (prsc->target == PIPE_TEXTURE_3D) { 757 tex.image_depth = prsc->depth0; 758 } else { 759 tex.image_depth = (cso->u.tex.last_layer - 760 cso->u.tex.first_layer) + 1; 761 } 762 763 tex.srgb = util_format_is_srgb(cso->format); 764 765 tex.base_level = cso->u.tex.first_level; 766#if V3D_VERSION >= 40 767 tex.max_level = cso->u.tex.last_level; 768 /* Note that we don't have a job to reference the texture's sBO 769 * at state create time, so any time this sampler view is used 770 * we need to add the texture to the job. 771 */ 772 tex.texture_base_pointer = cl_address(NULL, 773 rsc->bo->offset + 774 rsc->slices[0].offset + 775 cso->u.tex.first_layer * 776 rsc->cube_map_stride), 777 778 tex.swizzle_r = translate_swizzle(so->swizzle[0]); 779 tex.swizzle_g = translate_swizzle(so->swizzle[1]); 780 tex.swizzle_b = translate_swizzle(so->swizzle[2]); 781 tex.swizzle_a = translate_swizzle(so->swizzle[3]); 782#endif 783 tex.array_stride_64_byte_aligned = rsc->cube_map_stride / 64; 784 785 if (prsc->nr_samples > 1 && V3D_VERSION < 40) { 786 /* Using texture views to reinterpret formats on our 787 * MSAA textures won't work, because we don't lay out 788 * the bits in memory as it's expected -- for example, 789 * RGBA8 and RGB10_A2 are compatible in the 790 * ARB_texture_view spec, but in HW we lay them out as 791 * 32bpp RGBA8 and 64bpp RGBA16F. Just assert for now 792 * to catch failures. 793 * 794 * We explicitly allow remapping S8Z24 to RGBA8888 for 795 * v3d_blit.c's stencil blits. 796 */ 797 assert((util_format_linear(cso->format) == 798 util_format_linear(prsc->format)) || 799 (prsc->format == PIPE_FORMAT_S8_UINT_Z24_UNORM && 800 cso->format == PIPE_FORMAT_R8G8B8A8_UNORM)); 801 uint32_t output_image_format = 802 v3d_get_rt_format(&screen->devinfo, cso->format); 803 uint32_t internal_type; 804 uint32_t internal_bpp; 805 v3d_get_internal_type_bpp_for_output_format(&screen->devinfo, 806 output_image_format, 807 &internal_type, 808 &internal_bpp); 809 810 switch (internal_type) { 811 case V3D_INTERNAL_TYPE_8: 812 tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8; 813 break; 814 case V3D_INTERNAL_TYPE_16F: 815 tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F; 816 break; 817 default: 818 unreachable("Bad MSAA texture type"); 819 } 820 821 /* sRGB was stored in the tile buffer as linear and 822 * would have been encoded to sRGB on resolved tile 823 * buffer store. Note that this means we would need 824 * shader code if we wanted to read an MSAA sRGB 825 * texture without sRGB decode. 826 */ 827 tex.srgb = false; 828 } else { 829 tex.texture_type = v3d_get_tex_format(&screen->devinfo, 830 cso->format); 831 } 832 833 /* Since other platform devices may produce UIF images even 834 * when they're not big enough for V3D to assume they're UIF, 835 * we force images with level 0 as UIF to be always treated 836 * that way. 837 */ 838 tex.level_0_is_strictly_uif = (rsc->slices[0].tiling == 839 VC5_TILING_UIF_XOR || 840 rsc->slices[0].tiling == 841 VC5_TILING_UIF_NO_XOR); 842 tex.level_0_xor_enable = (rsc->slices[0].tiling == 843 VC5_TILING_UIF_XOR); 844 845 if (tex.level_0_is_strictly_uif) 846 tex.level_0_ub_pad = rsc->slices[0].ub_pad; 847 848#if V3D_VERSION >= 40 849 if (tex.uif_xor_disable || 850 tex.level_0_is_strictly_uif) { 851 tex.extended = true; 852 } 853#endif /* V3D_VERSION >= 40 */ 854 }; 855 856 return &so->base; 857} 858 859static void 860v3d_sampler_view_destroy(struct pipe_context *pctx, 861 struct pipe_sampler_view *psview) 862{ 863 struct v3d_sampler_view *sview = v3d_sampler_view(psview); 864 865 v3d_bo_unreference(&sview->bo); 866 pipe_resource_reference(&psview->texture, NULL); 867 free(psview); 868} 869 870static void 871v3d_set_sampler_views(struct pipe_context *pctx, 872 enum pipe_shader_type shader, 873 unsigned start, unsigned nr, 874 struct pipe_sampler_view **views) 875{ 876 struct v3d_context *v3d = v3d_context(pctx); 877 struct v3d_texture_stateobj *stage_tex = v3d_get_stage_tex(v3d, shader); 878 unsigned i; 879 unsigned new_nr = 0; 880 881 assert(start == 0); 882 883 for (i = 0; i < nr; i++) { 884 if (views[i]) 885 new_nr = i + 1; 886 pipe_sampler_view_reference(&stage_tex->textures[i], views[i]); 887 } 888 889 for (; i < stage_tex->num_textures; i++) { 890 pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 891 } 892 893 stage_tex->num_textures = new_nr; 894} 895 896static struct pipe_stream_output_target * 897v3d_create_stream_output_target(struct pipe_context *pctx, 898 struct pipe_resource *prsc, 899 unsigned buffer_offset, 900 unsigned buffer_size) 901{ 902 struct pipe_stream_output_target *target; 903 904 target = CALLOC_STRUCT(pipe_stream_output_target); 905 if (!target) 906 return NULL; 907 908 pipe_reference_init(&target->reference, 1); 909 pipe_resource_reference(&target->buffer, prsc); 910 911 target->context = pctx; 912 target->buffer_offset = buffer_offset; 913 target->buffer_size = buffer_size; 914 915 return target; 916} 917 918static void 919v3d_stream_output_target_destroy(struct pipe_context *pctx, 920 struct pipe_stream_output_target *target) 921{ 922 pipe_resource_reference(&target->buffer, NULL); 923 free(target); 924} 925 926static void 927v3d_set_stream_output_targets(struct pipe_context *pctx, 928 unsigned num_targets, 929 struct pipe_stream_output_target **targets, 930 const unsigned *offsets) 931{ 932 struct v3d_context *ctx = v3d_context(pctx); 933 struct v3d_streamout_stateobj *so = &ctx->streamout; 934 unsigned i; 935 936 assert(num_targets <= ARRAY_SIZE(so->targets)); 937 938 for (i = 0; i < num_targets; i++) { 939 if (offsets[i] != -1) 940 so->offsets[i] = offsets[i]; 941 942 pipe_so_target_reference(&so->targets[i], targets[i]); 943 } 944 945 for (; i < so->num_targets; i++) 946 pipe_so_target_reference(&so->targets[i], NULL); 947 948 so->num_targets = num_targets; 949 950 ctx->dirty |= VC5_DIRTY_STREAMOUT; 951} 952 953void 954v3dX(state_init)(struct pipe_context *pctx) 955{ 956 pctx->set_blend_color = v3d_set_blend_color; 957 pctx->set_stencil_ref = v3d_set_stencil_ref; 958 pctx->set_clip_state = v3d_set_clip_state; 959 pctx->set_sample_mask = v3d_set_sample_mask; 960 pctx->set_constant_buffer = v3d_set_constant_buffer; 961 pctx->set_framebuffer_state = v3d_set_framebuffer_state; 962 pctx->set_polygon_stipple = v3d_set_polygon_stipple; 963 pctx->set_scissor_states = v3d_set_scissor_states; 964 pctx->set_viewport_states = v3d_set_viewport_states; 965 966 pctx->set_vertex_buffers = v3d_set_vertex_buffers; 967 968 pctx->create_blend_state = v3d_create_blend_state; 969 pctx->bind_blend_state = v3d_blend_state_bind; 970 pctx->delete_blend_state = v3d_generic_cso_state_delete; 971 972 pctx->create_rasterizer_state = v3d_create_rasterizer_state; 973 pctx->bind_rasterizer_state = v3d_rasterizer_state_bind; 974 pctx->delete_rasterizer_state = v3d_generic_cso_state_delete; 975 976 pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state; 977 pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind; 978 pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete; 979 980 pctx->create_vertex_elements_state = v3d_vertex_state_create; 981 pctx->delete_vertex_elements_state = v3d_vertex_state_delete; 982 pctx->bind_vertex_elements_state = v3d_vertex_state_bind; 983 984 pctx->create_sampler_state = v3d_create_sampler_state; 985 pctx->delete_sampler_state = v3d_sampler_state_delete; 986 pctx->bind_sampler_states = v3d_sampler_states_bind; 987 988 pctx->create_sampler_view = v3d_create_sampler_view; 989 pctx->sampler_view_destroy = v3d_sampler_view_destroy; 990 pctx->set_sampler_views = v3d_set_sampler_views; 991 992 pctx->create_stream_output_target = v3d_create_stream_output_target; 993 pctx->stream_output_target_destroy = v3d_stream_output_target_destroy; 994 pctx->set_stream_output_targets = v3d_set_stream_output_targets; 995} 996