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 const struct pipe_vertex_buffer *vb) 317{ 318 struct vc4_context *vc4 = vc4_context(pctx); 319 struct vc4_vertexbuf_stateobj *so = &vc4->vertexbuf; 320 321 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, 322 start_slot, count); 323 so->count = util_last_bit(so->enabled_mask); 324 325 vc4->dirty |= VC4_DIRTY_VTXBUF; 326} 327 328static void 329vc4_blend_state_bind(struct pipe_context *pctx, void *hwcso) 330{ 331 struct vc4_context *vc4 = vc4_context(pctx); 332 vc4->blend = hwcso; 333 vc4->dirty |= VC4_DIRTY_BLEND; 334} 335 336static void 337vc4_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) 338{ 339 struct vc4_context *vc4 = vc4_context(pctx); 340 struct vc4_rasterizer_state *rast = hwcso; 341 342 if (vc4->rasterizer && rast && 343 vc4->rasterizer->base.flatshade != rast->base.flatshade) { 344 vc4->dirty |= VC4_DIRTY_FLAT_SHADE_FLAGS; 345 } 346 347 vc4->rasterizer = hwcso; 348 vc4->dirty |= VC4_DIRTY_RASTERIZER; 349} 350 351static void 352vc4_zsa_state_bind(struct pipe_context *pctx, void *hwcso) 353{ 354 struct vc4_context *vc4 = vc4_context(pctx); 355 vc4->zsa = hwcso; 356 vc4->dirty |= VC4_DIRTY_ZSA; 357} 358 359static void * 360vc4_vertex_state_create(struct pipe_context *pctx, unsigned num_elements, 361 const struct pipe_vertex_element *elements) 362{ 363 struct vc4_vertex_stateobj *so = CALLOC_STRUCT(vc4_vertex_stateobj); 364 365 if (!so) 366 return NULL; 367 368 memcpy(so->pipe, elements, sizeof(*elements) * num_elements); 369 so->num_elements = num_elements; 370 371 return so; 372} 373 374static void 375vc4_vertex_state_bind(struct pipe_context *pctx, void *hwcso) 376{ 377 struct vc4_context *vc4 = vc4_context(pctx); 378 vc4->vtx = hwcso; 379 vc4->dirty |= VC4_DIRTY_VTXSTATE; 380} 381 382static void 383vc4_set_constant_buffer(struct pipe_context *pctx, 384 enum pipe_shader_type shader, uint index, 385 const struct pipe_constant_buffer *cb) 386{ 387 struct vc4_context *vc4 = vc4_context(pctx); 388 struct vc4_constbuf_stateobj *so = &vc4->constbuf[shader]; 389 390 /* Note that the state tracker can unbind constant buffers by 391 * passing NULL here. 392 */ 393 if (unlikely(!cb)) { 394 so->enabled_mask &= ~(1 << index); 395 so->dirty_mask &= ~(1 << index); 396 return; 397 } 398 399 if (index == 1 && so->cb[index].buffer_size != cb->buffer_size) 400 vc4->dirty |= VC4_DIRTY_UBO_1_SIZE; 401 402 pipe_resource_reference(&so->cb[index].buffer, cb->buffer); 403 so->cb[index].buffer_offset = cb->buffer_offset; 404 so->cb[index].buffer_size = cb->buffer_size; 405 so->cb[index].user_buffer = cb->user_buffer; 406 407 so->enabled_mask |= 1 << index; 408 so->dirty_mask |= 1 << index; 409 vc4->dirty |= VC4_DIRTY_CONSTBUF; 410} 411 412static void 413vc4_set_framebuffer_state(struct pipe_context *pctx, 414 const struct pipe_framebuffer_state *framebuffer) 415{ 416 struct vc4_context *vc4 = vc4_context(pctx); 417 struct pipe_framebuffer_state *cso = &vc4->framebuffer; 418 419 vc4->job = NULL; 420 421 util_copy_framebuffer_state(cso, framebuffer); 422 423 /* Nonzero texture mipmap levels are laid out as if they were in 424 * power-of-two-sized spaces. The renderbuffer config infers its 425 * stride from the width parameter, so we need to configure our 426 * framebuffer. Note that if the z/color buffers were mismatched 427 * sizes, we wouldn't be able to do this. 428 */ 429 if (cso->cbufs[0] && cso->cbufs[0]->u.tex.level) { 430 struct vc4_resource *rsc = 431 vc4_resource(cso->cbufs[0]->texture); 432 cso->width = 433 (rsc->slices[cso->cbufs[0]->u.tex.level].stride / 434 rsc->cpp); 435 } else if (cso->zsbuf && cso->zsbuf->u.tex.level){ 436 struct vc4_resource *rsc = 437 vc4_resource(cso->zsbuf->texture); 438 cso->width = 439 (rsc->slices[cso->zsbuf->u.tex.level].stride / 440 rsc->cpp); 441 } 442 443 vc4->dirty |= VC4_DIRTY_FRAMEBUFFER; 444} 445 446static struct vc4_texture_stateobj * 447vc4_get_stage_tex(struct vc4_context *vc4, enum pipe_shader_type shader) 448{ 449 switch (shader) { 450 case PIPE_SHADER_FRAGMENT: 451 vc4->dirty |= VC4_DIRTY_FRAGTEX; 452 return &vc4->fragtex; 453 break; 454 case PIPE_SHADER_VERTEX: 455 vc4->dirty |= VC4_DIRTY_VERTTEX; 456 return &vc4->verttex; 457 break; 458 default: 459 fprintf(stderr, "Unknown shader target %d\n", shader); 460 abort(); 461 } 462} 463 464static uint32_t translate_wrap(uint32_t p_wrap, bool using_nearest) 465{ 466 switch (p_wrap) { 467 case PIPE_TEX_WRAP_REPEAT: 468 return 0; 469 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 470 return 1; 471 case PIPE_TEX_WRAP_MIRROR_REPEAT: 472 return 2; 473 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 474 return 3; 475 case PIPE_TEX_WRAP_CLAMP: 476 return (using_nearest ? 1 : 3); 477 default: 478 fprintf(stderr, "Unknown wrap mode %d\n", p_wrap); 479 assert(!"not reached"); 480 return 0; 481 } 482} 483 484static void * 485vc4_create_sampler_state(struct pipe_context *pctx, 486 const struct pipe_sampler_state *cso) 487{ 488 static const uint8_t minfilter_map[6] = { 489 VC4_TEX_P1_MINFILT_NEAR_MIP_NEAR, 490 VC4_TEX_P1_MINFILT_LIN_MIP_NEAR, 491 VC4_TEX_P1_MINFILT_NEAR_MIP_LIN, 492 VC4_TEX_P1_MINFILT_LIN_MIP_LIN, 493 VC4_TEX_P1_MINFILT_NEAREST, 494 VC4_TEX_P1_MINFILT_LINEAR, 495 }; 496 static const uint32_t magfilter_map[] = { 497 [PIPE_TEX_FILTER_NEAREST] = VC4_TEX_P1_MAGFILT_NEAREST, 498 [PIPE_TEX_FILTER_LINEAR] = VC4_TEX_P1_MAGFILT_LINEAR, 499 }; 500 bool either_nearest = 501 (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST || 502 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST); 503 struct vc4_sampler_state *so = CALLOC_STRUCT(vc4_sampler_state); 504 505 if (!so) 506 return NULL; 507 508 memcpy(so, cso, sizeof(*cso)); 509 510 so->texture_p1 = 511 (VC4_SET_FIELD(magfilter_map[cso->mag_img_filter], 512 VC4_TEX_P1_MAGFILT) | 513 VC4_SET_FIELD(minfilter_map[cso->min_mip_filter * 2 + 514 cso->min_img_filter], 515 VC4_TEX_P1_MINFILT) | 516 VC4_SET_FIELD(translate_wrap(cso->wrap_s, either_nearest), 517 VC4_TEX_P1_WRAP_S) | 518 VC4_SET_FIELD(translate_wrap(cso->wrap_t, either_nearest), 519 VC4_TEX_P1_WRAP_T)); 520 521 return so; 522} 523 524static void 525vc4_sampler_states_bind(struct pipe_context *pctx, 526 enum pipe_shader_type shader, unsigned start, 527 unsigned nr, void **hwcso) 528{ 529 struct vc4_context *vc4 = vc4_context(pctx); 530 struct vc4_texture_stateobj *stage_tex = vc4_get_stage_tex(vc4, shader); 531 532 assert(start == 0); 533 unsigned i; 534 unsigned new_nr = 0; 535 536 for (i = 0; i < nr; i++) { 537 if (hwcso[i]) 538 new_nr = i + 1; 539 stage_tex->samplers[i] = hwcso[i]; 540 } 541 542 for (; i < stage_tex->num_samplers; i++) { 543 stage_tex->samplers[i] = NULL; 544 } 545 546 stage_tex->num_samplers = new_nr; 547} 548 549static struct pipe_sampler_view * 550vc4_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, 551 const struct pipe_sampler_view *cso) 552{ 553 struct vc4_sampler_view *so = CALLOC_STRUCT(vc4_sampler_view); 554 struct vc4_resource *rsc = vc4_resource(prsc); 555 556 if (!so) 557 return NULL; 558 559 so->base = *cso; 560 561 so->base.texture = NULL; 562 pipe_resource_reference(&so->base.texture, prsc); 563 so->base.reference.count = 1; 564 so->base.context = pctx; 565 566 /* There is no hardware level clamping, and the start address of a 567 * texture may be misaligned, so in that case we have to copy to a 568 * temporary. 569 * 570 * Also, Raspberry Pi doesn't support sampling from raster textures, 571 * so we also have to copy to a temporary then. 572 */ 573 if ((cso->u.tex.first_level && 574 (cso->u.tex.first_level != cso->u.tex.last_level)) || 575 rsc->vc4_format == VC4_TEXTURE_TYPE_RGBA32R || 576 rsc->vc4_format == ~0) { 577 struct vc4_resource *shadow_parent = rsc; 578 struct pipe_resource tmpl = { 579 .target = prsc->target, 580 .format = prsc->format, 581 .width0 = u_minify(prsc->width0, 582 cso->u.tex.first_level), 583 .height0 = u_minify(prsc->height0, 584 cso->u.tex.first_level), 585 .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 586 .last_level = cso->u.tex.last_level - cso->u.tex.first_level, 587 .nr_samples = prsc->nr_samples, 588 }; 589 590 /* Create the shadow texture. The rest of the texture 591 * parameter setup will use the shadow. 592 */ 593 prsc = vc4_resource_create(pctx->screen, &tmpl); 594 if (!prsc) { 595 free(so); 596 return NULL; 597 } 598 rsc = vc4_resource(prsc); 599 vc4_bo_label(vc4_screen(pctx->screen), rsc->bo, 600 "tiling shadow %dx%d", 601 tmpl.width0, tmpl.height0); 602 603 /* Flag it as needing update of the contents from the parent. */ 604 rsc->writes = shadow_parent->writes - 1; 605 assert(rsc->vc4_format != VC4_TEXTURE_TYPE_RGBA32R); 606 607 so->texture = prsc; 608 } else { 609 pipe_resource_reference(&so->texture, prsc); 610 611 if (cso->u.tex.first_level) { 612 so->force_first_level = true; 613 } 614 } 615 616 so->texture_p0 = 617 (VC4_SET_FIELD((rsc->slices[0].offset + 618 cso->u.tex.first_layer * 619 rsc->cube_map_stride) >> 12, VC4_TEX_P0_OFFSET) | 620 VC4_SET_FIELD(rsc->vc4_format & 15, VC4_TEX_P0_TYPE) | 621 VC4_SET_FIELD(so->force_first_level ? 622 cso->u.tex.last_level : 623 cso->u.tex.last_level - 624 cso->u.tex.first_level, VC4_TEX_P0_MIPLVLS) | 625 VC4_SET_FIELD(cso->target == PIPE_TEXTURE_CUBE, 626 VC4_TEX_P0_CMMODE)); 627 so->texture_p1 = 628 (VC4_SET_FIELD(rsc->vc4_format >> 4, VC4_TEX_P1_TYPE4) | 629 VC4_SET_FIELD(prsc->height0 & 2047, VC4_TEX_P1_HEIGHT) | 630 VC4_SET_FIELD(prsc->width0 & 2047, VC4_TEX_P1_WIDTH)); 631 632 if (prsc->format == PIPE_FORMAT_ETC1_RGB8) 633 so->texture_p1 |= VC4_TEX_P1_ETCFLIP_MASK; 634 635 return &so->base; 636} 637 638static void 639vc4_sampler_view_destroy(struct pipe_context *pctx, 640 struct pipe_sampler_view *pview) 641{ 642 struct vc4_sampler_view *view = vc4_sampler_view(pview); 643 pipe_resource_reference(&pview->texture, NULL); 644 pipe_resource_reference(&view->texture, NULL); 645 free(view); 646} 647 648static void 649vc4_set_sampler_views(struct pipe_context *pctx, 650 enum pipe_shader_type shader, 651 unsigned start, unsigned nr, 652 struct pipe_sampler_view **views) 653{ 654 struct vc4_context *vc4 = vc4_context(pctx); 655 struct vc4_texture_stateobj *stage_tex = vc4_get_stage_tex(vc4, shader); 656 unsigned i; 657 unsigned new_nr = 0; 658 659 assert(start == 0); 660 661 for (i = 0; i < nr; i++) { 662 if (views[i]) 663 new_nr = i + 1; 664 pipe_sampler_view_reference(&stage_tex->textures[i], views[i]); 665 } 666 667 for (; i < stage_tex->num_textures; i++) { 668 pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 669 } 670 671 stage_tex->num_textures = new_nr; 672} 673 674void 675vc4_state_init(struct pipe_context *pctx) 676{ 677 pctx->set_blend_color = vc4_set_blend_color; 678 pctx->set_stencil_ref = vc4_set_stencil_ref; 679 pctx->set_clip_state = vc4_set_clip_state; 680 pctx->set_sample_mask = vc4_set_sample_mask; 681 pctx->set_constant_buffer = vc4_set_constant_buffer; 682 pctx->set_framebuffer_state = vc4_set_framebuffer_state; 683 pctx->set_polygon_stipple = vc4_set_polygon_stipple; 684 pctx->set_scissor_states = vc4_set_scissor_states; 685 pctx->set_viewport_states = vc4_set_viewport_states; 686 687 pctx->set_vertex_buffers = vc4_set_vertex_buffers; 688 689 pctx->create_blend_state = vc4_create_blend_state; 690 pctx->bind_blend_state = vc4_blend_state_bind; 691 pctx->delete_blend_state = vc4_generic_cso_state_delete; 692 693 pctx->create_rasterizer_state = vc4_create_rasterizer_state; 694 pctx->bind_rasterizer_state = vc4_rasterizer_state_bind; 695 pctx->delete_rasterizer_state = vc4_generic_cso_state_delete; 696 697 pctx->create_depth_stencil_alpha_state = vc4_create_depth_stencil_alpha_state; 698 pctx->bind_depth_stencil_alpha_state = vc4_zsa_state_bind; 699 pctx->delete_depth_stencil_alpha_state = vc4_generic_cso_state_delete; 700 701 pctx->create_vertex_elements_state = vc4_vertex_state_create; 702 pctx->delete_vertex_elements_state = vc4_generic_cso_state_delete; 703 pctx->bind_vertex_elements_state = vc4_vertex_state_bind; 704 705 pctx->create_sampler_state = vc4_create_sampler_state; 706 pctx->delete_sampler_state = vc4_generic_cso_state_delete; 707 pctx->bind_sampler_states = vc4_sampler_states_bind; 708 709 pctx->create_sampler_view = vc4_create_sampler_view; 710 pctx->sampler_view_destroy = vc4_sampler_view_destroy; 711 pctx->set_sampler_views = vc4_set_sampler_views; 712} 713