1/* 2 * Copyright © 2014 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_framebuffer.h" 27#include "util/u_inlines.h" 28#include "util/u_math.h" 29#include "util/u_memory.h" 30#include "util/u_helpers.h" 31 32#include "vc4_context.h" 33 34static void * 35vc4_generic_cso_state_create(const void *src, uint32_t size) 36{ 37 void *dst = calloc(1, size); 38 if (!dst) 39 return NULL; 40 memcpy(dst, src, size); 41 return dst; 42} 43 44static void 45vc4_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso) 46{ 47 free(hwcso); 48} 49 50static void 51vc4_set_blend_color(struct pipe_context *pctx, 52 const struct pipe_blend_color *blend_color) 53{ 54 struct vc4_context *vc4 = vc4_context(pctx); 55 vc4->blend_color.f = *blend_color; 56 for (int i = 0; i < 4; i++) 57 vc4->blend_color.ub[i] = float_to_ubyte(blend_color->color[i]); 58 vc4->dirty |= VC4_DIRTY_BLEND_COLOR; 59} 60 61static void 62vc4_set_stencil_ref(struct pipe_context *pctx, 63 const struct pipe_stencil_ref stencil_ref) 64{ 65 struct vc4_context *vc4 = vc4_context(pctx); 66 vc4->stencil_ref = stencil_ref; 67 vc4->dirty |= VC4_DIRTY_STENCIL_REF; 68} 69 70static void 71vc4_set_clip_state(struct pipe_context *pctx, 72 const struct pipe_clip_state *clip) 73{ 74 struct vc4_context *vc4 = vc4_context(pctx); 75 vc4->clip = *clip; 76 vc4->dirty |= VC4_DIRTY_CLIP; 77} 78 79static void 80vc4_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 81{ 82 struct vc4_context *vc4 = vc4_context(pctx); 83 vc4->sample_mask = sample_mask & ((1 << VC4_MAX_SAMPLES) - 1); 84 vc4->dirty |= VC4_DIRTY_SAMPLE_MASK; 85} 86 87static uint16_t 88float_to_187_half(float f) 89{ 90 return fui(f) >> 16; 91} 92 93static void * 94vc4_create_rasterizer_state(struct pipe_context *pctx, 95 const struct pipe_rasterizer_state *cso) 96{ 97 struct vc4_rasterizer_state *so; 98 struct V3D21_DEPTH_OFFSET depth_offset = { V3D21_DEPTH_OFFSET_header }; 99 struct V3D21_POINT_SIZE point_size = { V3D21_POINT_SIZE_header }; 100 struct V3D21_LINE_WIDTH line_width = { V3D21_LINE_WIDTH_header }; 101 102 so = CALLOC_STRUCT(vc4_rasterizer_state); 103 if (!so) 104 return NULL; 105 106 so->base = *cso; 107 108 if (!(cso->cull_face & PIPE_FACE_FRONT)) 109 so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_PRIM_FRONT; 110 if (!(cso->cull_face & PIPE_FACE_BACK)) 111 so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_PRIM_BACK; 112 113 /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835, 114 * BCM21553). 115 */ 116 point_size.point_size = MAX2(cso->point_size, .125f); 117 118 line_width.line_width = cso->line_width; 119 120 if (cso->front_ccw) 121 so->config_bits[0] |= VC4_CONFIG_BITS_CW_PRIMITIVES; 122 123 if (cso->offset_tri) { 124 so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_DEPTH_OFFSET; 125 126 depth_offset.depth_offset_units = 127 float_to_187_half(cso->offset_units); 128 depth_offset.depth_offset_factor = 129 float_to_187_half(cso->offset_scale); 130 } 131 132 if (cso->multisample) 133 so->config_bits[0] |= VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_4X; 134 135 V3D21_DEPTH_OFFSET_pack(NULL, so->packed.depth_offset, &depth_offset); 136 V3D21_POINT_SIZE_pack(NULL, so->packed.point_size, &point_size); 137 V3D21_LINE_WIDTH_pack(NULL, so->packed.line_width, &line_width); 138 139 if (cso->tile_raster_order_fixed) { 140 so->tile_raster_order_flags |= VC4_SUBMIT_CL_FIXED_RCL_ORDER; 141 if (cso->tile_raster_order_increasing_x) { 142 so->tile_raster_order_flags |= 143 VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X; 144 } 145 if (cso->tile_raster_order_increasing_y) { 146 so->tile_raster_order_flags |= 147 VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y; 148 } 149 } 150 151 return so; 152} 153 154/* Blend state is baked into shaders. */ 155static void * 156vc4_create_blend_state(struct pipe_context *pctx, 157 const struct pipe_blend_state *cso) 158{ 159 return vc4_generic_cso_state_create(cso, sizeof(*cso)); 160} 161 162/** 163 * The TLB_STENCIL_SETUP data has a little bitfield for common writemask 164 * values, so you don't have to do a separate writemask setup. 165 */ 166static uint8_t 167tlb_stencil_setup_writemask(uint8_t mask) 168{ 169 switch (mask) { 170 case 0x1: return 0; 171 case 0x3: return 1; 172 case 0xf: return 2; 173 case 0xff: return 3; 174 default: return 0xff; 175 } 176} 177 178static uint32_t 179tlb_stencil_setup_bits(const struct pipe_stencil_state *state, 180 uint8_t writemask_bits) 181{ 182 static const uint8_t op_map[] = { 183 [PIPE_STENCIL_OP_ZERO] = 0, 184 [PIPE_STENCIL_OP_KEEP] = 1, 185 [PIPE_STENCIL_OP_REPLACE] = 2, 186 [PIPE_STENCIL_OP_INCR] = 3, 187 [PIPE_STENCIL_OP_DECR] = 4, 188 [PIPE_STENCIL_OP_INVERT] = 5, 189 [PIPE_STENCIL_OP_INCR_WRAP] = 6, 190 [PIPE_STENCIL_OP_DECR_WRAP] = 7, 191 }; 192 uint32_t bits = 0; 193 194 if (writemask_bits != 0xff) 195 bits |= writemask_bits << 28; 196 bits |= op_map[state->zfail_op] << 25; 197 bits |= op_map[state->zpass_op] << 22; 198 bits |= op_map[state->fail_op] << 19; 199 bits |= state->func << 16; 200 /* Ref is filled in at uniform upload time */ 201 bits |= state->valuemask << 0; 202 203 return bits; 204} 205 206static void * 207vc4_create_depth_stencil_alpha_state(struct pipe_context *pctx, 208 const struct pipe_depth_stencil_alpha_state *cso) 209{ 210 struct vc4_depth_stencil_alpha_state *so; 211 212 so = CALLOC_STRUCT(vc4_depth_stencil_alpha_state); 213 if (!so) 214 return NULL; 215 216 so->base = *cso; 217 218 /* We always keep the early Z state correct, since a later state using 219 * early Z may want it. 220 */ 221 so->config_bits[2] |= VC4_CONFIG_BITS_EARLY_Z_UPDATE; 222 223 if (cso->depth_enabled) { 224 if (cso->depth_writemask) { 225 so->config_bits[1] |= VC4_CONFIG_BITS_Z_UPDATE; 226 } 227 so->config_bits[1] |= (cso->depth_func << 228 VC4_CONFIG_BITS_DEPTH_FUNC_SHIFT); 229 230 /* We only handle early Z in the < direction because otherwise 231 * we'd have to runtime guess which direction to set in the 232 * render config. 233 */ 234 if ((cso->depth_func == PIPE_FUNC_LESS || 235 cso->depth_func == PIPE_FUNC_LEQUAL) && 236 (!cso->stencil[0].enabled || 237 (cso->stencil[0].zfail_op == PIPE_STENCIL_OP_KEEP && 238 (!cso->stencil[1].enabled || 239 cso->stencil[1].zfail_op == PIPE_STENCIL_OP_KEEP)))) { 240 so->config_bits[2] |= VC4_CONFIG_BITS_EARLY_Z; 241 } 242 } else { 243 so->config_bits[1] |= (PIPE_FUNC_ALWAYS << 244 VC4_CONFIG_BITS_DEPTH_FUNC_SHIFT); 245 } 246 247 if (cso->stencil[0].enabled) { 248 const struct pipe_stencil_state *front = &cso->stencil[0]; 249 const struct pipe_stencil_state *back = &cso->stencil[1]; 250 251 uint8_t front_writemask_bits = 252 tlb_stencil_setup_writemask(front->writemask); 253 uint8_t back_writemask = front->writemask; 254 uint8_t back_writemask_bits = front_writemask_bits; 255 256 so->stencil_uniforms[0] = 257 tlb_stencil_setup_bits(front, front_writemask_bits); 258 if (back->enabled) { 259 back_writemask = back->writemask; 260 back_writemask_bits = 261 tlb_stencil_setup_writemask(back->writemask); 262 263 so->stencil_uniforms[0] |= (1 << 30); 264 so->stencil_uniforms[1] = 265 tlb_stencil_setup_bits(back, back_writemask_bits); 266 so->stencil_uniforms[1] |= (2 << 30); 267 } else { 268 so->stencil_uniforms[0] |= (3 << 30); 269 } 270 271 if (front_writemask_bits == 0xff || 272 back_writemask_bits == 0xff) { 273 so->stencil_uniforms[2] = (front->writemask | 274 (back_writemask << 8)); 275 } 276 } 277 278 return so; 279} 280 281static void 282vc4_set_polygon_stipple(struct pipe_context *pctx, 283 const struct pipe_poly_stipple *stipple) 284{ 285 struct vc4_context *vc4 = vc4_context(pctx); 286 vc4->stipple = *stipple; 287 vc4->dirty |= VC4_DIRTY_STIPPLE; 288} 289 290static void 291vc4_set_scissor_states(struct pipe_context *pctx, 292 unsigned start_slot, 293 unsigned num_scissors, 294 const struct pipe_scissor_state *scissor) 295{ 296 struct vc4_context *vc4 = vc4_context(pctx); 297 298 vc4->scissor = *scissor; 299 vc4->dirty |= VC4_DIRTY_SCISSOR; 300} 301 302static void 303vc4_set_viewport_states(struct pipe_context *pctx, 304 unsigned start_slot, 305 unsigned num_viewports, 306 const struct pipe_viewport_state *viewport) 307{ 308 struct vc4_context *vc4 = vc4_context(pctx); 309 vc4->viewport = *viewport; 310 vc4->dirty |= VC4_DIRTY_VIEWPORT; 311} 312 313static void 314vc4_set_vertex_buffers(struct pipe_context *pctx, 315 unsigned start_slot, unsigned count, 316 unsigned unbind_num_trailing_slots, 317 bool take_ownership, 318 const struct pipe_vertex_buffer *vb) 319{ 320 struct vc4_context *vc4 = vc4_context(pctx); 321 struct vc4_vertexbuf_stateobj *so = &vc4->vertexbuf; 322 323 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, 324 start_slot, count, 325 unbind_num_trailing_slots, 326 take_ownership); 327 so->count = util_last_bit(so->enabled_mask); 328 329 vc4->dirty |= VC4_DIRTY_VTXBUF; 330} 331 332static void 333vc4_blend_state_bind(struct pipe_context *pctx, void *hwcso) 334{ 335 struct vc4_context *vc4 = vc4_context(pctx); 336 vc4->blend = hwcso; 337 vc4->dirty |= VC4_DIRTY_BLEND; 338} 339 340static void 341vc4_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) 342{ 343 struct vc4_context *vc4 = vc4_context(pctx); 344 struct vc4_rasterizer_state *rast = hwcso; 345 346 if (vc4->rasterizer && rast && 347 vc4->rasterizer->base.flatshade != rast->base.flatshade) { 348 vc4->dirty |= VC4_DIRTY_FLAT_SHADE_FLAGS; 349 } 350 351 vc4->rasterizer = hwcso; 352 vc4->dirty |= VC4_DIRTY_RASTERIZER; 353} 354 355static void 356vc4_zsa_state_bind(struct pipe_context *pctx, void *hwcso) 357{ 358 struct vc4_context *vc4 = vc4_context(pctx); 359 vc4->zsa = hwcso; 360 vc4->dirty |= VC4_DIRTY_ZSA; 361} 362 363static void * 364vc4_vertex_state_create(struct pipe_context *pctx, unsigned num_elements, 365 const struct pipe_vertex_element *elements) 366{ 367 struct vc4_vertex_stateobj *so = CALLOC_STRUCT(vc4_vertex_stateobj); 368 369 if (!so) 370 return NULL; 371 372 memcpy(so->pipe, elements, sizeof(*elements) * num_elements); 373 so->num_elements = num_elements; 374 375 return so; 376} 377 378static void 379vc4_vertex_state_bind(struct pipe_context *pctx, void *hwcso) 380{ 381 struct vc4_context *vc4 = vc4_context(pctx); 382 vc4->vtx = hwcso; 383 vc4->dirty |= VC4_DIRTY_VTXSTATE; 384} 385 386static void 387vc4_set_constant_buffer(struct pipe_context *pctx, 388 enum pipe_shader_type shader, uint index, 389 bool take_ownership, 390 const struct pipe_constant_buffer *cb) 391{ 392 struct vc4_context *vc4 = vc4_context(pctx); 393 struct vc4_constbuf_stateobj *so = &vc4->constbuf[shader]; 394 395 /* Note that the gallium frontend can unbind constant buffers by 396 * passing NULL here. 397 */ 398 if (unlikely(!cb)) { 399 so->enabled_mask &= ~(1 << index); 400 so->dirty_mask &= ~(1 << index); 401 return; 402 } 403 404 if (index == 1 && so->cb[index].buffer_size != cb->buffer_size) 405 vc4->dirty |= VC4_DIRTY_UBO_1_SIZE; 406 407 util_copy_constant_buffer(&so->cb[index], cb, take_ownership); 408 409 so->enabled_mask |= 1 << index; 410 so->dirty_mask |= 1 << index; 411 vc4->dirty |= VC4_DIRTY_CONSTBUF; 412} 413 414static void 415vc4_set_framebuffer_state(struct pipe_context *pctx, 416 const struct pipe_framebuffer_state *framebuffer) 417{ 418 struct vc4_context *vc4 = vc4_context(pctx); 419 struct pipe_framebuffer_state *cso = &vc4->framebuffer; 420 421 vc4->job = NULL; 422 423 util_copy_framebuffer_state(cso, framebuffer); 424 425 /* Nonzero texture mipmap levels are laid out as if they were in 426 * power-of-two-sized spaces. The renderbuffer config infers its 427 * stride from the width parameter, so we need to configure our 428 * framebuffer. Note that if the z/color buffers were mismatched 429 * sizes, we wouldn't be able to do this. 430 */ 431 if (cso->cbufs[0] && cso->cbufs[0]->u.tex.level) { 432 struct vc4_resource *rsc = 433 vc4_resource(cso->cbufs[0]->texture); 434 cso->width = 435 (rsc->slices[cso->cbufs[0]->u.tex.level].stride / 436 rsc->cpp); 437 } else if (cso->zsbuf && cso->zsbuf->u.tex.level){ 438 struct vc4_resource *rsc = 439 vc4_resource(cso->zsbuf->texture); 440 cso->width = 441 (rsc->slices[cso->zsbuf->u.tex.level].stride / 442 rsc->cpp); 443 } 444 445 vc4->dirty |= VC4_DIRTY_FRAMEBUFFER; 446} 447 448static struct vc4_texture_stateobj * 449vc4_get_stage_tex(struct vc4_context *vc4, enum pipe_shader_type shader) 450{ 451 switch (shader) { 452 case PIPE_SHADER_FRAGMENT: 453 vc4->dirty |= VC4_DIRTY_FRAGTEX; 454 return &vc4->fragtex; 455 break; 456 case PIPE_SHADER_VERTEX: 457 vc4->dirty |= VC4_DIRTY_VERTTEX; 458 return &vc4->verttex; 459 break; 460 default: 461 fprintf(stderr, "Unknown shader target %d\n", shader); 462 abort(); 463 } 464} 465 466static uint32_t translate_wrap(uint32_t p_wrap, bool using_nearest) 467{ 468 switch (p_wrap) { 469 case PIPE_TEX_WRAP_REPEAT: 470 return 0; 471 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 472 return 1; 473 case PIPE_TEX_WRAP_MIRROR_REPEAT: 474 return 2; 475 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 476 return 3; 477 case PIPE_TEX_WRAP_CLAMP: 478 return (using_nearest ? 1 : 3); 479 default: 480 fprintf(stderr, "Unknown wrap mode %d\n", p_wrap); 481 assert(!"not reached"); 482 return 0; 483 } 484} 485 486static void * 487vc4_create_sampler_state(struct pipe_context *pctx, 488 const struct pipe_sampler_state *cso) 489{ 490 static const uint8_t minfilter_map[6] = { 491 VC4_TEX_P1_MINFILT_NEAR_MIP_NEAR, 492 VC4_TEX_P1_MINFILT_LIN_MIP_NEAR, 493 VC4_TEX_P1_MINFILT_NEAR_MIP_LIN, 494 VC4_TEX_P1_MINFILT_LIN_MIP_LIN, 495 VC4_TEX_P1_MINFILT_NEAREST, 496 VC4_TEX_P1_MINFILT_LINEAR, 497 }; 498 static const uint32_t magfilter_map[] = { 499 [PIPE_TEX_FILTER_NEAREST] = VC4_TEX_P1_MAGFILT_NEAREST, 500 [PIPE_TEX_FILTER_LINEAR] = VC4_TEX_P1_MAGFILT_LINEAR, 501 }; 502 bool either_nearest = 503 (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST || 504 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST); 505 struct vc4_sampler_state *so = CALLOC_STRUCT(vc4_sampler_state); 506 507 if (!so) 508 return NULL; 509 510 memcpy(so, cso, sizeof(*cso)); 511 512 so->texture_p1 = 513 (VC4_SET_FIELD(magfilter_map[cso->mag_img_filter], 514 VC4_TEX_P1_MAGFILT) | 515 VC4_SET_FIELD(minfilter_map[cso->min_mip_filter * 2 + 516 cso->min_img_filter], 517 VC4_TEX_P1_MINFILT) | 518 VC4_SET_FIELD(translate_wrap(cso->wrap_s, either_nearest), 519 VC4_TEX_P1_WRAP_S) | 520 VC4_SET_FIELD(translate_wrap(cso->wrap_t, either_nearest), 521 VC4_TEX_P1_WRAP_T)); 522 523 return so; 524} 525 526static void 527vc4_sampler_states_bind(struct pipe_context *pctx, 528 enum pipe_shader_type shader, unsigned start, 529 unsigned nr, void **hwcso) 530{ 531 struct vc4_context *vc4 = vc4_context(pctx); 532 struct vc4_texture_stateobj *stage_tex = vc4_get_stage_tex(vc4, shader); 533 534 assert(start == 0); 535 unsigned i; 536 unsigned new_nr = 0; 537 538 for (i = 0; i < nr; i++) { 539 if (hwcso[i]) 540 new_nr = i + 1; 541 stage_tex->samplers[i] = hwcso[i]; 542 } 543 544 for (; i < stage_tex->num_samplers; i++) { 545 stage_tex->samplers[i] = NULL; 546 } 547 548 stage_tex->num_samplers = new_nr; 549} 550 551static struct pipe_sampler_view * 552vc4_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, 553 const struct pipe_sampler_view *cso) 554{ 555 struct vc4_sampler_view *so = CALLOC_STRUCT(vc4_sampler_view); 556 struct vc4_resource *rsc = vc4_resource(prsc); 557 558 if (!so) 559 return NULL; 560 561 so->base = *cso; 562 563 so->base.texture = NULL; 564 pipe_resource_reference(&so->base.texture, prsc); 565 so->base.reference.count = 1; 566 so->base.context = pctx; 567 568 /* There is no hardware level clamping, and the start address of a 569 * texture may be misaligned, so in that case we have to copy to a 570 * temporary. 571 * 572 * Also, Raspberry Pi doesn't support sampling from raster textures, 573 * so we also have to copy to a temporary then. 574 */ 575 if ((cso->u.tex.first_level && 576 (cso->u.tex.first_level != cso->u.tex.last_level)) || 577 rsc->vc4_format == VC4_TEXTURE_TYPE_RGBA32R || 578 rsc->vc4_format == ~0) { 579 struct vc4_resource *shadow_parent = rsc; 580 struct pipe_resource tmpl = { 581 .target = prsc->target, 582 .format = prsc->format, 583 .width0 = u_minify(prsc->width0, 584 cso->u.tex.first_level), 585 .height0 = u_minify(prsc->height0, 586 cso->u.tex.first_level), 587 .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 588 .last_level = cso->u.tex.last_level - cso->u.tex.first_level, 589 .nr_samples = prsc->nr_samples, 590 }; 591 592 /* Create the shadow texture. The rest of the texture 593 * parameter setup will use the shadow. 594 */ 595 prsc = vc4_resource_create(pctx->screen, &tmpl); 596 if (!prsc) { 597 free(so); 598 return NULL; 599 } 600 rsc = vc4_resource(prsc); 601 vc4_bo_label(vc4_screen(pctx->screen), rsc->bo, 602 "tiling shadow %dx%d", 603 tmpl.width0, tmpl.height0); 604 605 /* Flag it as needing update of the contents from the parent. */ 606 rsc->writes = shadow_parent->writes - 1; 607 assert(rsc->vc4_format != VC4_TEXTURE_TYPE_RGBA32R); 608 609 so->texture = prsc; 610 } else { 611 pipe_resource_reference(&so->texture, prsc); 612 613 if (cso->u.tex.first_level) { 614 so->force_first_level = true; 615 } 616 } 617 618 so->texture_p0 = 619 (VC4_SET_FIELD((rsc->slices[0].offset + 620 cso->u.tex.first_layer * 621 rsc->cube_map_stride) >> 12, VC4_TEX_P0_OFFSET) | 622 VC4_SET_FIELD(rsc->vc4_format & 15, VC4_TEX_P0_TYPE) | 623 VC4_SET_FIELD(so->force_first_level ? 624 cso->u.tex.last_level : 625 cso->u.tex.last_level - 626 cso->u.tex.first_level, VC4_TEX_P0_MIPLVLS) | 627 VC4_SET_FIELD(cso->target == PIPE_TEXTURE_CUBE, 628 VC4_TEX_P0_CMMODE)); 629 so->texture_p1 = 630 (VC4_SET_FIELD(rsc->vc4_format >> 4, VC4_TEX_P1_TYPE4) | 631 VC4_SET_FIELD(prsc->height0 & 2047, VC4_TEX_P1_HEIGHT) | 632 VC4_SET_FIELD(prsc->width0 & 2047, VC4_TEX_P1_WIDTH)); 633 634 if (prsc->format == PIPE_FORMAT_ETC1_RGB8) 635 so->texture_p1 |= VC4_TEX_P1_ETCFLIP_MASK; 636 637 return &so->base; 638} 639 640static void 641vc4_sampler_view_destroy(struct pipe_context *pctx, 642 struct pipe_sampler_view *pview) 643{ 644 struct vc4_sampler_view *view = vc4_sampler_view(pview); 645 pipe_resource_reference(&pview->texture, NULL); 646 pipe_resource_reference(&view->texture, NULL); 647 free(view); 648} 649 650static void 651vc4_set_sampler_views(struct pipe_context *pctx, 652 enum pipe_shader_type shader, 653 unsigned start, unsigned nr, 654 unsigned unbind_num_trailing_slots, 655 bool take_ownership, 656 struct pipe_sampler_view **views) 657{ 658 struct vc4_context *vc4 = vc4_context(pctx); 659 struct vc4_texture_stateobj *stage_tex = vc4_get_stage_tex(vc4, shader); 660 unsigned i; 661 unsigned new_nr = 0; 662 663 assert(start == 0); 664 665 for (i = 0; i < nr; i++) { 666 if (views[i]) 667 new_nr = i + 1; 668 if (take_ownership) { 669 pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 670 stage_tex->textures[i] = views[i]; 671 } else { 672 pipe_sampler_view_reference(&stage_tex->textures[i], views[i]); 673 } 674 } 675 676 for (; i < stage_tex->num_textures; i++) { 677 pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 678 } 679 680 stage_tex->num_textures = new_nr; 681} 682 683void 684vc4_state_init(struct pipe_context *pctx) 685{ 686 pctx->set_blend_color = vc4_set_blend_color; 687 pctx->set_stencil_ref = vc4_set_stencil_ref; 688 pctx->set_clip_state = vc4_set_clip_state; 689 pctx->set_sample_mask = vc4_set_sample_mask; 690 pctx->set_constant_buffer = vc4_set_constant_buffer; 691 pctx->set_framebuffer_state = vc4_set_framebuffer_state; 692 pctx->set_polygon_stipple = vc4_set_polygon_stipple; 693 pctx->set_scissor_states = vc4_set_scissor_states; 694 pctx->set_viewport_states = vc4_set_viewport_states; 695 696 pctx->set_vertex_buffers = vc4_set_vertex_buffers; 697 698 pctx->create_blend_state = vc4_create_blend_state; 699 pctx->bind_blend_state = vc4_blend_state_bind; 700 pctx->delete_blend_state = vc4_generic_cso_state_delete; 701 702 pctx->create_rasterizer_state = vc4_create_rasterizer_state; 703 pctx->bind_rasterizer_state = vc4_rasterizer_state_bind; 704 pctx->delete_rasterizer_state = vc4_generic_cso_state_delete; 705 706 pctx->create_depth_stencil_alpha_state = vc4_create_depth_stencil_alpha_state; 707 pctx->bind_depth_stencil_alpha_state = vc4_zsa_state_bind; 708 pctx->delete_depth_stencil_alpha_state = vc4_generic_cso_state_delete; 709 710 pctx->create_vertex_elements_state = vc4_vertex_state_create; 711 pctx->delete_vertex_elements_state = vc4_generic_cso_state_delete; 712 pctx->bind_vertex_elements_state = vc4_vertex_state_bind; 713 714 pctx->create_sampler_state = vc4_create_sampler_state; 715 pctx->delete_sampler_state = vc4_generic_cso_state_delete; 716 pctx->bind_sampler_states = vc4_sampler_states_bind; 717 718 pctx->create_sampler_view = vc4_create_sampler_view; 719 pctx->sampler_view_destroy = vc4_sampler_view_destroy; 720 pctx->set_sampler_views = vc4_set_sampler_views; 721} 722