1/* 2 * Copyright 2010 Christoph Bumiller 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23#include "pipe/p_defines.h" 24#include "util/u_framebuffer.h" 25#include "util/u_helpers.h" 26#include "util/u_inlines.h" 27#include "util/u_transfer.h" 28 29#include "tgsi/tgsi_parse.h" 30#include "compiler/nir/nir.h" 31 32#include "nvc0/nvc0_stateobj.h" 33#include "nvc0/nvc0_context.h" 34#include "nvc0/nvc0_query_hw.h" 35 36#include "nvc0/nvc0_3d.xml.h" 37 38#include "nouveau_gldefs.h" 39 40static inline uint32_t 41nvc0_colormask(unsigned mask) 42{ 43 uint32_t ret = 0; 44 45 if (mask & PIPE_MASK_R) 46 ret |= 0x0001; 47 if (mask & PIPE_MASK_G) 48 ret |= 0x0010; 49 if (mask & PIPE_MASK_B) 50 ret |= 0x0100; 51 if (mask & PIPE_MASK_A) 52 ret |= 0x1000; 53 54 return ret; 55} 56 57#define NVC0_BLEND_FACTOR_CASE(a, b) \ 58 case PIPE_BLENDFACTOR_##a: return NV50_BLEND_FACTOR_##b 59 60static inline uint32_t 61nvc0_blend_fac(unsigned factor) 62{ 63 switch (factor) { 64 NVC0_BLEND_FACTOR_CASE(ONE, ONE); 65 NVC0_BLEND_FACTOR_CASE(SRC_COLOR, SRC_COLOR); 66 NVC0_BLEND_FACTOR_CASE(SRC_ALPHA, SRC_ALPHA); 67 NVC0_BLEND_FACTOR_CASE(DST_ALPHA, DST_ALPHA); 68 NVC0_BLEND_FACTOR_CASE(DST_COLOR, DST_COLOR); 69 NVC0_BLEND_FACTOR_CASE(SRC_ALPHA_SATURATE, SRC_ALPHA_SATURATE); 70 NVC0_BLEND_FACTOR_CASE(CONST_COLOR, CONSTANT_COLOR); 71 NVC0_BLEND_FACTOR_CASE(CONST_ALPHA, CONSTANT_ALPHA); 72 NVC0_BLEND_FACTOR_CASE(SRC1_COLOR, SRC1_COLOR); 73 NVC0_BLEND_FACTOR_CASE(SRC1_ALPHA, SRC1_ALPHA); 74 NVC0_BLEND_FACTOR_CASE(ZERO, ZERO); 75 NVC0_BLEND_FACTOR_CASE(INV_SRC_COLOR, ONE_MINUS_SRC_COLOR); 76 NVC0_BLEND_FACTOR_CASE(INV_SRC_ALPHA, ONE_MINUS_SRC_ALPHA); 77 NVC0_BLEND_FACTOR_CASE(INV_DST_ALPHA, ONE_MINUS_DST_ALPHA); 78 NVC0_BLEND_FACTOR_CASE(INV_DST_COLOR, ONE_MINUS_DST_COLOR); 79 NVC0_BLEND_FACTOR_CASE(INV_CONST_COLOR, ONE_MINUS_CONSTANT_COLOR); 80 NVC0_BLEND_FACTOR_CASE(INV_CONST_ALPHA, ONE_MINUS_CONSTANT_ALPHA); 81 NVC0_BLEND_FACTOR_CASE(INV_SRC1_COLOR, ONE_MINUS_SRC1_COLOR); 82 NVC0_BLEND_FACTOR_CASE(INV_SRC1_ALPHA, ONE_MINUS_SRC1_ALPHA); 83 default: 84 return NV50_BLEND_FACTOR_ZERO; 85 } 86} 87 88static void * 89nvc0_blend_state_create(struct pipe_context *pipe, 90 const struct pipe_blend_state *cso) 91{ 92 struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj); 93 int i; 94 int r; /* reference */ 95 uint32_t ms; 96 uint8_t blend_en = 0; 97 bool indep_masks = false; 98 bool indep_funcs = false; 99 100 so->pipe = *cso; 101 102 /* check which states actually have differing values */ 103 if (cso->independent_blend_enable) { 104 for (r = 0; r < 8 && !cso->rt[r].blend_enable; ++r); 105 blend_en |= 1 << r; 106 for (i = r + 1; i < 8; ++i) { 107 if (!cso->rt[i].blend_enable) 108 continue; 109 blend_en |= 1 << i; 110 if (cso->rt[i].rgb_func != cso->rt[r].rgb_func || 111 cso->rt[i].rgb_src_factor != cso->rt[r].rgb_src_factor || 112 cso->rt[i].rgb_dst_factor != cso->rt[r].rgb_dst_factor || 113 cso->rt[i].alpha_func != cso->rt[r].alpha_func || 114 cso->rt[i].alpha_src_factor != cso->rt[r].alpha_src_factor || 115 cso->rt[i].alpha_dst_factor != cso->rt[r].alpha_dst_factor) { 116 indep_funcs = true; 117 break; 118 } 119 } 120 for (; i < 8; ++i) 121 blend_en |= (cso->rt[i].blend_enable ? 1 : 0) << i; 122 123 for (i = 1; i < 8; ++i) { 124 if (cso->rt[i].colormask != cso->rt[0].colormask) { 125 indep_masks = true; 126 break; 127 } 128 } 129 } else { 130 r = 0; 131 if (cso->rt[0].blend_enable) 132 blend_en = 0xff; 133 } 134 135 if (cso->logicop_enable) { 136 SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2); 137 SB_DATA (so, 1); 138 SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); 139 140 SB_IMMED_3D(so, MACRO_BLEND_ENABLES, 0); 141 } else { 142 SB_IMMED_3D(so, LOGIC_OP_ENABLE, 0); 143 144 SB_IMMED_3D(so, BLEND_INDEPENDENT, indep_funcs); 145 SB_IMMED_3D(so, MACRO_BLEND_ENABLES, blend_en); 146 if (indep_funcs) { 147 for (i = 0; i < 8; ++i) { 148 if (cso->rt[i].blend_enable) { 149 SB_BEGIN_3D(so, IBLEND_EQUATION_RGB(i), 6); 150 SB_DATA (so, nvgl_blend_eqn(cso->rt[i].rgb_func)); 151 SB_DATA (so, nvc0_blend_fac(cso->rt[i].rgb_src_factor)); 152 SB_DATA (so, nvc0_blend_fac(cso->rt[i].rgb_dst_factor)); 153 SB_DATA (so, nvgl_blend_eqn(cso->rt[i].alpha_func)); 154 SB_DATA (so, nvc0_blend_fac(cso->rt[i].alpha_src_factor)); 155 SB_DATA (so, nvc0_blend_fac(cso->rt[i].alpha_dst_factor)); 156 } 157 } 158 } else 159 if (blend_en) { 160 SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5); 161 SB_DATA (so, nvgl_blend_eqn(cso->rt[r].rgb_func)); 162 SB_DATA (so, nvc0_blend_fac(cso->rt[r].rgb_src_factor)); 163 SB_DATA (so, nvc0_blend_fac(cso->rt[r].rgb_dst_factor)); 164 SB_DATA (so, nvgl_blend_eqn(cso->rt[r].alpha_func)); 165 SB_DATA (so, nvc0_blend_fac(cso->rt[r].alpha_src_factor)); 166 SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1); 167 SB_DATA (so, nvc0_blend_fac(cso->rt[r].alpha_dst_factor)); 168 } 169 170 SB_IMMED_3D(so, COLOR_MASK_COMMON, !indep_masks); 171 if (indep_masks) { 172 SB_BEGIN_3D(so, COLOR_MASK(0), 8); 173 for (i = 0; i < 8; ++i) 174 SB_DATA(so, nvc0_colormask(cso->rt[i].colormask)); 175 } else { 176 SB_BEGIN_3D(so, COLOR_MASK(0), 1); 177 SB_DATA (so, nvc0_colormask(cso->rt[0].colormask)); 178 } 179 } 180 181 ms = 0; 182 if (cso->alpha_to_coverage) 183 ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE; 184 if (cso->alpha_to_one) 185 ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE; 186 187 SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1); 188 SB_DATA (so, ms); 189 190 assert(so->size <= ARRAY_SIZE(so->state)); 191 return so; 192} 193 194static void 195nvc0_blend_state_bind(struct pipe_context *pipe, void *hwcso) 196{ 197 struct nvc0_context *nvc0 = nvc0_context(pipe); 198 199 nvc0->blend = hwcso; 200 nvc0->dirty_3d |= NVC0_NEW_3D_BLEND; 201} 202 203static void 204nvc0_blend_state_delete(struct pipe_context *pipe, void *hwcso) 205{ 206 FREE(hwcso); 207} 208 209/* NOTE: ignoring line_last_pixel */ 210static void * 211nvc0_rasterizer_state_create(struct pipe_context *pipe, 212 const struct pipe_rasterizer_state *cso) 213{ 214 struct nvc0_rasterizer_stateobj *so; 215 uint16_t class_3d = nouveau_screen(pipe->screen)->class_3d; 216 uint32_t reg; 217 218 so = CALLOC_STRUCT(nvc0_rasterizer_stateobj); 219 if (!so) 220 return NULL; 221 so->pipe = *cso; 222 223 /* Scissor enables are handled in scissor state, we will not want to 224 * always emit 16 commands, one for each scissor rectangle, here. 225 */ 226 227 SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); 228 SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); 229 230 SB_IMMED_3D(so, VERT_COLOR_CLAMP_EN, cso->clamp_vertex_color); 231 SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1); 232 SB_DATA (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000); 233 234 SB_IMMED_3D(so, MULTISAMPLE_ENABLE, cso->multisample); 235 236 SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth); 237 /* On GM20x+, LINE_WIDTH_SMOOTH controls both aliased and smooth 238 * rendering and LINE_WIDTH_ALIASED seems to be ignored 239 */ 240 if (cso->line_smooth || cso->multisample || class_3d >= GM200_3D_CLASS) 241 SB_BEGIN_3D(so, LINE_WIDTH_SMOOTH, 1); 242 else 243 SB_BEGIN_3D(so, LINE_WIDTH_ALIASED, 1); 244 SB_DATA (so, fui(cso->line_width)); 245 246 SB_IMMED_3D(so, LINE_STIPPLE_ENABLE, cso->line_stipple_enable); 247 if (cso->line_stipple_enable) { 248 SB_BEGIN_3D(so, LINE_STIPPLE_PATTERN, 1); 249 SB_DATA (so, (cso->line_stipple_pattern << 8) | 250 cso->line_stipple_factor); 251 252 } 253 254 SB_IMMED_3D(so, VP_POINT_SIZE, cso->point_size_per_vertex); 255 if (!cso->point_size_per_vertex) { 256 SB_BEGIN_3D(so, POINT_SIZE, 1); 257 SB_DATA (so, fui(cso->point_size)); 258 } 259 260 reg = (cso->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT) ? 261 NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT : 262 NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT; 263 264 SB_BEGIN_3D(so, POINT_COORD_REPLACE, 1); 265 SB_DATA (so, ((cso->sprite_coord_enable & 0xff) << 3) | reg); 266 SB_IMMED_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); 267 SB_IMMED_3D(so, POINT_SMOOTH_ENABLE, cso->point_smooth); 268 269 if (class_3d >= GM200_3D_CLASS) { 270 SB_IMMED_3D(so, FILL_RECTANGLE, 271 cso->fill_front == PIPE_POLYGON_MODE_FILL_RECTANGLE ? 272 NVC0_3D_FILL_RECTANGLE_ENABLE : 0); 273 } 274 275 SB_BEGIN_3D(so, MACRO_POLYGON_MODE_FRONT, 1); 276 SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); 277 SB_BEGIN_3D(so, MACRO_POLYGON_MODE_BACK, 1); 278 SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); 279 SB_IMMED_3D(so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); 280 281 SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); 282 SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); 283 SB_DATA (so, cso->front_ccw ? NVC0_3D_FRONT_FACE_CCW : 284 NVC0_3D_FRONT_FACE_CW); 285 switch (cso->cull_face) { 286 case PIPE_FACE_FRONT_AND_BACK: 287 SB_DATA(so, NVC0_3D_CULL_FACE_FRONT_AND_BACK); 288 break; 289 case PIPE_FACE_FRONT: 290 SB_DATA(so, NVC0_3D_CULL_FACE_FRONT); 291 break; 292 case PIPE_FACE_BACK: 293 default: 294 SB_DATA(so, NVC0_3D_CULL_FACE_BACK); 295 break; 296 } 297 298 SB_IMMED_3D(so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); 299 SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3); 300 SB_DATA (so, cso->offset_point); 301 SB_DATA (so, cso->offset_line); 302 SB_DATA (so, cso->offset_tri); 303 304 if (cso->offset_point || cso->offset_line || cso->offset_tri) { 305 SB_BEGIN_3D(so, POLYGON_OFFSET_FACTOR, 1); 306 SB_DATA (so, fui(cso->offset_scale)); 307 if (!cso->offset_units_unscaled) { 308 SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1); 309 SB_DATA (so, fui(cso->offset_units * 2.0f)); 310 } 311 SB_BEGIN_3D(so, POLYGON_OFFSET_CLAMP, 1); 312 SB_DATA (so, fui(cso->offset_clamp)); 313 } 314 315 if (cso->depth_clip_near) 316 reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1; 317 else 318 reg = 319 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 | 320 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR | 321 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR | 322 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2; 323 324 SB_BEGIN_3D(so, VIEW_VOLUME_CLIP_CTRL, 1); 325 SB_DATA (so, reg); 326 327 SB_IMMED_3D(so, DEPTH_CLIP_NEGATIVE_Z, cso->clip_halfz); 328 329 SB_IMMED_3D(so, PIXEL_CENTER_INTEGER, !cso->half_pixel_center); 330 331 if (class_3d >= GM200_3D_CLASS) { 332 if (cso->conservative_raster_mode != PIPE_CONSERVATIVE_RASTER_OFF) { 333 bool post_snap = cso->conservative_raster_mode == 334 PIPE_CONSERVATIVE_RASTER_POST_SNAP; 335 uint32_t state = cso->subpixel_precision_x; 336 state |= cso->subpixel_precision_y << 4; 337 state |= (uint32_t)(cso->conservative_raster_dilate * 4) << 8; 338 state |= (post_snap || class_3d < GP100_3D_CLASS) ? 1 << 10 : 0; 339 SB_IMMED_3D(so, MACRO_CONSERVATIVE_RASTER_STATE, state); 340 } else { 341 SB_IMMED_3D(so, CONSERVATIVE_RASTER, 0); 342 } 343 } 344 345 assert(so->size <= ARRAY_SIZE(so->state)); 346 return (void *)so; 347} 348 349static void 350nvc0_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) 351{ 352 struct nvc0_context *nvc0 = nvc0_context(pipe); 353 354 nvc0->rast = hwcso; 355 nvc0->dirty_3d |= NVC0_NEW_3D_RASTERIZER; 356} 357 358static void 359nvc0_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) 360{ 361 FREE(hwcso); 362} 363 364static void * 365nvc0_zsa_state_create(struct pipe_context *pipe, 366 const struct pipe_depth_stencil_alpha_state *cso) 367{ 368 struct nvc0_zsa_stateobj *so = CALLOC_STRUCT(nvc0_zsa_stateobj); 369 370 so->pipe = *cso; 371 372 SB_IMMED_3D(so, DEPTH_TEST_ENABLE, cso->depth.enabled); 373 if (cso->depth.enabled) { 374 SB_IMMED_3D(so, DEPTH_WRITE_ENABLE, cso->depth.writemask); 375 SB_BEGIN_3D(so, DEPTH_TEST_FUNC, 1); 376 SB_DATA (so, nvgl_comparison_op(cso->depth.func)); 377 } 378 379 SB_IMMED_3D(so, DEPTH_BOUNDS_EN, cso->depth.bounds_test); 380 if (cso->depth.bounds_test) { 381 SB_BEGIN_3D(so, DEPTH_BOUNDS(0), 2); 382 SB_DATA (so, fui(cso->depth.bounds_min)); 383 SB_DATA (so, fui(cso->depth.bounds_max)); 384 } 385 386 if (cso->stencil[0].enabled) { 387 SB_BEGIN_3D(so, STENCIL_ENABLE, 5); 388 SB_DATA (so, 1); 389 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op)); 390 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); 391 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); 392 SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func)); 393 SB_BEGIN_3D(so, STENCIL_FRONT_FUNC_MASK, 2); 394 SB_DATA (so, cso->stencil[0].valuemask); 395 SB_DATA (so, cso->stencil[0].writemask); 396 } else { 397 SB_IMMED_3D(so, STENCIL_ENABLE, 0); 398 } 399 400 if (cso->stencil[1].enabled) { 401 assert(cso->stencil[0].enabled); 402 SB_BEGIN_3D(so, STENCIL_TWO_SIDE_ENABLE, 5); 403 SB_DATA (so, 1); 404 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op)); 405 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); 406 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); 407 SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func)); 408 SB_BEGIN_3D(so, STENCIL_BACK_MASK, 2); 409 SB_DATA (so, cso->stencil[1].writemask); 410 SB_DATA (so, cso->stencil[1].valuemask); 411 } else 412 if (cso->stencil[0].enabled) { 413 SB_IMMED_3D(so, STENCIL_TWO_SIDE_ENABLE, 0); 414 } 415 416 SB_IMMED_3D(so, ALPHA_TEST_ENABLE, cso->alpha.enabled); 417 if (cso->alpha.enabled) { 418 SB_BEGIN_3D(so, ALPHA_TEST_REF, 2); 419 SB_DATA (so, fui(cso->alpha.ref_value)); 420 SB_DATA (so, nvgl_comparison_op(cso->alpha.func)); 421 } 422 423 assert(so->size <= ARRAY_SIZE(so->state)); 424 return (void *)so; 425} 426 427static void 428nvc0_zsa_state_bind(struct pipe_context *pipe, void *hwcso) 429{ 430 struct nvc0_context *nvc0 = nvc0_context(pipe); 431 432 nvc0->zsa = hwcso; 433 nvc0->dirty_3d |= NVC0_NEW_3D_ZSA; 434} 435 436static void 437nvc0_zsa_state_delete(struct pipe_context *pipe, void *hwcso) 438{ 439 FREE(hwcso); 440} 441 442/* ====================== SAMPLERS AND TEXTURES ================================ 443 */ 444 445#define NV50_TSC_WRAP_CASE(n) \ 446 case PIPE_TEX_WRAP_##n: return NV50_TSC_WRAP_##n 447 448static void 449nvc0_sampler_state_delete(struct pipe_context *pipe, void *hwcso) 450{ 451 unsigned s, i; 452 453 for (s = 0; s < 6; ++s) 454 for (i = 0; i < nvc0_context(pipe)->num_samplers[s]; ++i) 455 if (nvc0_context(pipe)->samplers[s][i] == hwcso) 456 nvc0_context(pipe)->samplers[s][i] = NULL; 457 458 nvc0_screen_tsc_free(nvc0_context(pipe)->screen, nv50_tsc_entry(hwcso)); 459 460 FREE(hwcso); 461} 462 463static inline void 464nvc0_stage_sampler_states_bind(struct nvc0_context *nvc0, 465 unsigned s, 466 unsigned nr, void **hwcsos) 467{ 468 unsigned highest_found = 0; 469 unsigned i; 470 471 for (i = 0; i < nr; ++i) { 472 struct nv50_tsc_entry *hwcso = hwcsos ? nv50_tsc_entry(hwcsos[i]) : NULL; 473 struct nv50_tsc_entry *old = nvc0->samplers[s][i]; 474 475 if (hwcso) 476 highest_found = i; 477 478 if (hwcso == old) 479 continue; 480 nvc0->samplers_dirty[s] |= 1 << i; 481 482 nvc0->samplers[s][i] = hwcso; 483 if (old) 484 nvc0_screen_tsc_unlock(nvc0->screen, old); 485 } 486 if (nr >= nvc0->num_samplers[s]) 487 nvc0->num_samplers[s] = highest_found + 1; 488} 489 490static void 491nvc0_bind_sampler_states(struct pipe_context *pipe, 492 enum pipe_shader_type shader, 493 unsigned start, unsigned nr, void **samplers) 494{ 495 const unsigned s = nvc0_shader_stage(shader); 496 497 assert(start == 0); 498 nvc0_stage_sampler_states_bind(nvc0_context(pipe), s, nr, samplers); 499 500 if (s == 5) 501 nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SAMPLERS; 502 else 503 nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_SAMPLERS; 504} 505 506 507/* NOTE: only called when not referenced anywhere, won't be bound */ 508static void 509nvc0_sampler_view_destroy(struct pipe_context *pipe, 510 struct pipe_sampler_view *view) 511{ 512 pipe_resource_reference(&view->texture, NULL); 513 514 nvc0_screen_tic_free(nvc0_context(pipe)->screen, nv50_tic_entry(view)); 515 516 FREE(nv50_tic_entry(view)); 517} 518 519static inline void 520nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s, 521 unsigned nr, 522 struct pipe_sampler_view **views) 523{ 524 unsigned i; 525 526 for (i = 0; i < nr; ++i) { 527 struct pipe_sampler_view *view = views ? views[i] : NULL; 528 struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); 529 530 if (view == nvc0->textures[s][i]) 531 continue; 532 nvc0->textures_dirty[s] |= 1 << i; 533 534 if (view && view->texture) { 535 struct pipe_resource *res = view->texture; 536 if (res->target == PIPE_BUFFER && 537 (res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)) 538 nvc0->textures_coherent[s] |= 1 << i; 539 else 540 nvc0->textures_coherent[s] &= ~(1 << i); 541 } else { 542 nvc0->textures_coherent[s] &= ~(1 << i); 543 } 544 545 if (old) { 546 if (s == 5) 547 nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i)); 548 else 549 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i)); 550 nvc0_screen_tic_unlock(nvc0->screen, old); 551 } 552 553 pipe_sampler_view_reference(&nvc0->textures[s][i], view); 554 } 555 556 for (i = nr; i < nvc0->num_textures[s]; ++i) { 557 struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); 558 if (old) { 559 if (s == 5) 560 nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i)); 561 else 562 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i)); 563 nvc0_screen_tic_unlock(nvc0->screen, old); 564 pipe_sampler_view_reference(&nvc0->textures[s][i], NULL); 565 } 566 } 567 568 nvc0->num_textures[s] = nr; 569} 570 571static void 572nvc0_set_sampler_views(struct pipe_context *pipe, enum pipe_shader_type shader, 573 unsigned start, unsigned nr, 574 struct pipe_sampler_view **views) 575{ 576 const unsigned s = nvc0_shader_stage(shader); 577 578 assert(start == 0); 579 nvc0_stage_set_sampler_views(nvc0_context(pipe), s, nr, views); 580 581 if (s == 5) 582 nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_TEXTURES; 583 else 584 nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_TEXTURES; 585} 586 587/* ============================= SHADERS ======================================= 588 */ 589 590static void * 591nvc0_sp_state_create(struct pipe_context *pipe, 592 const struct pipe_shader_state *cso, unsigned type) 593{ 594 struct nvc0_program *prog; 595 596 prog = CALLOC_STRUCT(nvc0_program); 597 if (!prog) 598 return NULL; 599 600 prog->type = type; 601 prog->pipe.type = cso->type; 602 603 switch(cso->type) { 604 case PIPE_SHADER_IR_TGSI: 605 prog->pipe.tokens = tgsi_dup_tokens(cso->tokens); 606 break; 607 case PIPE_SHADER_IR_NIR: 608 prog->pipe.ir.nir = cso->ir.nir; 609 break; 610 default: 611 assert(!"unsupported IR!"); 612 free(prog); 613 return NULL; 614 } 615 616 if (cso->stream_output.num_outputs) 617 prog->pipe.stream_output = cso->stream_output; 618 619 prog->translated = nvc0_program_translate( 620 prog, nvc0_context(pipe)->screen->base.device->chipset, 621 &nouveau_context(pipe)->debug); 622 623 return (void *)prog; 624} 625 626static void 627nvc0_sp_state_delete(struct pipe_context *pipe, void *hwcso) 628{ 629 struct nvc0_program *prog = (struct nvc0_program *)hwcso; 630 631 nvc0_program_destroy(nvc0_context(pipe), prog); 632 633 if (prog->pipe.type == PIPE_SHADER_IR_TGSI) 634 FREE((void *)prog->pipe.tokens); 635 else if (prog->pipe.type == PIPE_SHADER_IR_NIR) 636 ralloc_free(prog->pipe.ir.nir); 637 FREE(prog); 638} 639 640static void * 641nvc0_vp_state_create(struct pipe_context *pipe, 642 const struct pipe_shader_state *cso) 643{ 644 return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_VERTEX); 645} 646 647static void 648nvc0_vp_state_bind(struct pipe_context *pipe, void *hwcso) 649{ 650 struct nvc0_context *nvc0 = nvc0_context(pipe); 651 652 nvc0->vertprog = hwcso; 653 nvc0->dirty_3d |= NVC0_NEW_3D_VERTPROG; 654} 655 656static void * 657nvc0_fp_state_create(struct pipe_context *pipe, 658 const struct pipe_shader_state *cso) 659{ 660 return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_FRAGMENT); 661} 662 663static void 664nvc0_fp_state_bind(struct pipe_context *pipe, void *hwcso) 665{ 666 struct nvc0_context *nvc0 = nvc0_context(pipe); 667 668 nvc0->fragprog = hwcso; 669 nvc0->dirty_3d |= NVC0_NEW_3D_FRAGPROG; 670} 671 672static void * 673nvc0_gp_state_create(struct pipe_context *pipe, 674 const struct pipe_shader_state *cso) 675{ 676 return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_GEOMETRY); 677} 678 679static void 680nvc0_gp_state_bind(struct pipe_context *pipe, void *hwcso) 681{ 682 struct nvc0_context *nvc0 = nvc0_context(pipe); 683 684 nvc0->gmtyprog = hwcso; 685 nvc0->dirty_3d |= NVC0_NEW_3D_GMTYPROG; 686} 687 688static void * 689nvc0_tcp_state_create(struct pipe_context *pipe, 690 const struct pipe_shader_state *cso) 691{ 692 return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_TESS_CTRL); 693} 694 695static void 696nvc0_tcp_state_bind(struct pipe_context *pipe, void *hwcso) 697{ 698 struct nvc0_context *nvc0 = nvc0_context(pipe); 699 700 nvc0->tctlprog = hwcso; 701 nvc0->dirty_3d |= NVC0_NEW_3D_TCTLPROG; 702} 703 704static void * 705nvc0_tep_state_create(struct pipe_context *pipe, 706 const struct pipe_shader_state *cso) 707{ 708 return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_TESS_EVAL); 709} 710 711static void 712nvc0_tep_state_bind(struct pipe_context *pipe, void *hwcso) 713{ 714 struct nvc0_context *nvc0 = nvc0_context(pipe); 715 716 nvc0->tevlprog = hwcso; 717 nvc0->dirty_3d |= NVC0_NEW_3D_TEVLPROG; 718} 719 720static void * 721nvc0_cp_state_create(struct pipe_context *pipe, 722 const struct pipe_compute_state *cso) 723{ 724 struct nvc0_program *prog; 725 726 prog = CALLOC_STRUCT(nvc0_program); 727 if (!prog) 728 return NULL; 729 prog->type = PIPE_SHADER_COMPUTE; 730 prog->pipe.type = cso->ir_type; 731 732 prog->cp.smem_size = cso->req_local_mem; 733 prog->cp.lmem_size = cso->req_private_mem; 734 prog->parm_size = cso->req_input_mem; 735 736 switch(cso->ir_type) { 737 case PIPE_SHADER_IR_TGSI: 738 prog->pipe.tokens = tgsi_dup_tokens((const struct tgsi_token *)cso->prog); 739 break; 740 case PIPE_SHADER_IR_NIR: 741 prog->pipe.ir.nir = (nir_shader *)cso->prog; 742 break; 743 default: 744 assert(!"unsupported IR!"); 745 free(prog); 746 return NULL; 747 } 748 749 prog->translated = nvc0_program_translate( 750 prog, nvc0_context(pipe)->screen->base.device->chipset, 751 &nouveau_context(pipe)->debug); 752 753 return (void *)prog; 754} 755 756static void 757nvc0_cp_state_bind(struct pipe_context *pipe, void *hwcso) 758{ 759 struct nvc0_context *nvc0 = nvc0_context(pipe); 760 761 nvc0->compprog = hwcso; 762 nvc0->dirty_cp |= NVC0_NEW_CP_PROGRAM; 763} 764 765static void 766nvc0_set_constant_buffer(struct pipe_context *pipe, 767 enum pipe_shader_type shader, uint index, 768 const struct pipe_constant_buffer *cb) 769{ 770 struct nvc0_context *nvc0 = nvc0_context(pipe); 771 struct pipe_resource *res = cb ? cb->buffer : NULL; 772 const unsigned s = nvc0_shader_stage(shader); 773 const unsigned i = index; 774 775 if (unlikely(shader == PIPE_SHADER_COMPUTE)) { 776 if (nvc0->constbuf[s][i].user) 777 nvc0->constbuf[s][i].u.buf = NULL; 778 else 779 if (nvc0->constbuf[s][i].u.buf) 780 nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_CB(i)); 781 782 nvc0->dirty_cp |= NVC0_NEW_CP_CONSTBUF; 783 } else { 784 if (nvc0->constbuf[s][i].user) 785 nvc0->constbuf[s][i].u.buf = NULL; 786 else 787 if (nvc0->constbuf[s][i].u.buf) 788 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_CB(s, i)); 789 790 nvc0->dirty_3d |= NVC0_NEW_3D_CONSTBUF; 791 } 792 nvc0->constbuf_dirty[s] |= 1 << i; 793 794 if (nvc0->constbuf[s][i].u.buf) 795 nv04_resource(nvc0->constbuf[s][i].u.buf)->cb_bindings[s] &= ~(1 << i); 796 pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, res); 797 798 nvc0->constbuf[s][i].user = (cb && cb->user_buffer) ? true : false; 799 if (nvc0->constbuf[s][i].user) { 800 nvc0->constbuf[s][i].u.data = cb->user_buffer; 801 nvc0->constbuf[s][i].size = MIN2(cb->buffer_size, 0x10000); 802 nvc0->constbuf_valid[s] |= 1 << i; 803 nvc0->constbuf_coherent[s] &= ~(1 << i); 804 } else 805 if (cb) { 806 nvc0->constbuf[s][i].offset = cb->buffer_offset; 807 nvc0->constbuf[s][i].size = MIN2(align(cb->buffer_size, 0x100), 0x10000); 808 nvc0->constbuf_valid[s] |= 1 << i; 809 if (res && res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT) 810 nvc0->constbuf_coherent[s] |= 1 << i; 811 else 812 nvc0->constbuf_coherent[s] &= ~(1 << i); 813 } 814 else { 815 nvc0->constbuf_valid[s] &= ~(1 << i); 816 nvc0->constbuf_coherent[s] &= ~(1 << i); 817 } 818} 819 820/* ============================================================================= 821 */ 822 823static void 824nvc0_set_blend_color(struct pipe_context *pipe, 825 const struct pipe_blend_color *bcol) 826{ 827 struct nvc0_context *nvc0 = nvc0_context(pipe); 828 829 nvc0->blend_colour = *bcol; 830 nvc0->dirty_3d |= NVC0_NEW_3D_BLEND_COLOUR; 831} 832 833static void 834nvc0_set_stencil_ref(struct pipe_context *pipe, 835 const struct pipe_stencil_ref *sr) 836{ 837 struct nvc0_context *nvc0 = nvc0_context(pipe); 838 839 nvc0->stencil_ref = *sr; 840 nvc0->dirty_3d |= NVC0_NEW_3D_STENCIL_REF; 841} 842 843static void 844nvc0_set_clip_state(struct pipe_context *pipe, 845 const struct pipe_clip_state *clip) 846{ 847 struct nvc0_context *nvc0 = nvc0_context(pipe); 848 849 memcpy(nvc0->clip.ucp, clip->ucp, sizeof(clip->ucp)); 850 851 nvc0->dirty_3d |= NVC0_NEW_3D_CLIP; 852} 853 854static void 855nvc0_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) 856{ 857 struct nvc0_context *nvc0 = nvc0_context(pipe); 858 859 nvc0->sample_mask = sample_mask; 860 nvc0->dirty_3d |= NVC0_NEW_3D_SAMPLE_MASK; 861} 862 863static void 864nvc0_set_min_samples(struct pipe_context *pipe, unsigned min_samples) 865{ 866 struct nvc0_context *nvc0 = nvc0_context(pipe); 867 868 if (nvc0->min_samples != min_samples) { 869 nvc0->min_samples = min_samples; 870 nvc0->dirty_3d |= NVC0_NEW_3D_MIN_SAMPLES; 871 } 872} 873 874static void 875nvc0_set_framebuffer_state(struct pipe_context *pipe, 876 const struct pipe_framebuffer_state *fb) 877{ 878 struct nvc0_context *nvc0 = nvc0_context(pipe); 879 880 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB); 881 882 util_copy_framebuffer_state(&nvc0->framebuffer, fb); 883 884 nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER | NVC0_NEW_3D_SAMPLE_LOCATIONS | 885 NVC0_NEW_3D_TEXTURES; 886 nvc0->dirty_cp |= NVC0_NEW_CP_TEXTURES; 887} 888 889static void 890nvc0_set_sample_locations(struct pipe_context *pipe, 891 size_t size, const uint8_t *locations) 892{ 893 struct nvc0_context *nvc0 = nvc0_context(pipe); 894 895 nvc0->sample_locations_enabled = size && locations; 896 if (size > sizeof(nvc0->sample_locations)) 897 size = sizeof(nvc0->sample_locations); 898 memcpy(nvc0->sample_locations, locations, size); 899 900 nvc0->dirty_3d |= NVC0_NEW_3D_SAMPLE_LOCATIONS; 901} 902 903static void 904nvc0_set_polygon_stipple(struct pipe_context *pipe, 905 const struct pipe_poly_stipple *stipple) 906{ 907 struct nvc0_context *nvc0 = nvc0_context(pipe); 908 909 nvc0->stipple = *stipple; 910 nvc0->dirty_3d |= NVC0_NEW_3D_STIPPLE; 911} 912 913static void 914nvc0_set_scissor_states(struct pipe_context *pipe, 915 unsigned start_slot, 916 unsigned num_scissors, 917 const struct pipe_scissor_state *scissor) 918{ 919 struct nvc0_context *nvc0 = nvc0_context(pipe); 920 int i; 921 922 assert(start_slot + num_scissors <= NVC0_MAX_VIEWPORTS); 923 for (i = 0; i < num_scissors; i++) { 924 if (!memcmp(&nvc0->scissors[start_slot + i], &scissor[i], sizeof(*scissor))) 925 continue; 926 nvc0->scissors[start_slot + i] = scissor[i]; 927 nvc0->scissors_dirty |= 1 << (start_slot + i); 928 nvc0->dirty_3d |= NVC0_NEW_3D_SCISSOR; 929 } 930} 931 932static void 933nvc0_set_viewport_states(struct pipe_context *pipe, 934 unsigned start_slot, 935 unsigned num_viewports, 936 const struct pipe_viewport_state *vpt) 937{ 938 struct nvc0_context *nvc0 = nvc0_context(pipe); 939 int i; 940 941 assert(start_slot + num_viewports <= NVC0_MAX_VIEWPORTS); 942 for (i = 0; i < num_viewports; i++) { 943 if (!memcmp(&nvc0->viewports[start_slot + i], &vpt[i], sizeof(*vpt))) 944 continue; 945 nvc0->viewports[start_slot + i] = vpt[i]; 946 nvc0->viewports_dirty |= 1 << (start_slot + i); 947 nvc0->dirty_3d |= NVC0_NEW_3D_VIEWPORT; 948 } 949 950} 951 952static void 953nvc0_set_window_rectangles(struct pipe_context *pipe, 954 boolean include, 955 unsigned num_rectangles, 956 const struct pipe_scissor_state *rectangles) 957{ 958 struct nvc0_context *nvc0 = nvc0_context(pipe); 959 960 nvc0->window_rect.inclusive = include; 961 nvc0->window_rect.rects = MIN2(num_rectangles, NVC0_MAX_WINDOW_RECTANGLES); 962 memcpy(nvc0->window_rect.rect, rectangles, 963 sizeof(struct pipe_scissor_state) * nvc0->window_rect.rects); 964 965 nvc0->dirty_3d |= NVC0_NEW_3D_WINDOW_RECTS; 966} 967 968static void 969nvc0_set_tess_state(struct pipe_context *pipe, 970 const float default_tess_outer[4], 971 const float default_tess_inner[2]) 972{ 973 struct nvc0_context *nvc0 = nvc0_context(pipe); 974 975 memcpy(nvc0->default_tess_outer, default_tess_outer, 4 * sizeof(float)); 976 memcpy(nvc0->default_tess_inner, default_tess_inner, 2 * sizeof(float)); 977 nvc0->dirty_3d |= NVC0_NEW_3D_TESSFACTOR; 978} 979 980static void 981nvc0_set_vertex_buffers(struct pipe_context *pipe, 982 unsigned start_slot, unsigned count, 983 const struct pipe_vertex_buffer *vb) 984{ 985 struct nvc0_context *nvc0 = nvc0_context(pipe); 986 unsigned i; 987 988 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX); 989 nvc0->dirty_3d |= NVC0_NEW_3D_ARRAYS; 990 991 util_set_vertex_buffers_count(nvc0->vtxbuf, &nvc0->num_vtxbufs, vb, 992 start_slot, count); 993 994 if (!vb) { 995 nvc0->vbo_user &= ~(((1ull << count) - 1) << start_slot); 996 nvc0->constant_vbos &= ~(((1ull << count) - 1) << start_slot); 997 nvc0->vtxbufs_coherent &= ~(((1ull << count) - 1) << start_slot); 998 return; 999 } 1000 1001 for (i = 0; i < count; ++i) { 1002 unsigned dst_index = start_slot + i; 1003 1004 if (vb[i].is_user_buffer) { 1005 nvc0->vbo_user |= 1 << dst_index; 1006 if (!vb[i].stride && nvc0->screen->eng3d->oclass < GM107_3D_CLASS) 1007 nvc0->constant_vbos |= 1 << dst_index; 1008 else 1009 nvc0->constant_vbos &= ~(1 << dst_index); 1010 nvc0->vtxbufs_coherent &= ~(1 << dst_index); 1011 } else { 1012 nvc0->vbo_user &= ~(1 << dst_index); 1013 nvc0->constant_vbos &= ~(1 << dst_index); 1014 1015 if (vb[i].buffer.resource && 1016 vb[i].buffer.resource->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT) 1017 nvc0->vtxbufs_coherent |= (1 << dst_index); 1018 else 1019 nvc0->vtxbufs_coherent &= ~(1 << dst_index); 1020 } 1021 } 1022} 1023 1024static void 1025nvc0_vertex_state_bind(struct pipe_context *pipe, void *hwcso) 1026{ 1027 struct nvc0_context *nvc0 = nvc0_context(pipe); 1028 1029 nvc0->vertex = hwcso; 1030 nvc0->dirty_3d |= NVC0_NEW_3D_VERTEX; 1031} 1032 1033static struct pipe_stream_output_target * 1034nvc0_so_target_create(struct pipe_context *pipe, 1035 struct pipe_resource *res, 1036 unsigned offset, unsigned size) 1037{ 1038 struct nv04_resource *buf = (struct nv04_resource *)res; 1039 struct nvc0_so_target *targ = MALLOC_STRUCT(nvc0_so_target); 1040 if (!targ) 1041 return NULL; 1042 1043 targ->pq = pipe->create_query(pipe, NVC0_HW_QUERY_TFB_BUFFER_OFFSET, 0); 1044 if (!targ->pq) { 1045 FREE(targ); 1046 return NULL; 1047 } 1048 targ->clean = true; 1049 1050 targ->pipe.buffer_size = size; 1051 targ->pipe.buffer_offset = offset; 1052 targ->pipe.context = pipe; 1053 targ->pipe.buffer = NULL; 1054 pipe_resource_reference(&targ->pipe.buffer, res); 1055 pipe_reference_init(&targ->pipe.reference, 1); 1056 1057 assert(buf->base.target == PIPE_BUFFER); 1058 util_range_add(&buf->valid_buffer_range, offset, offset + size); 1059 1060 return &targ->pipe; 1061} 1062 1063static void 1064nvc0_so_target_save_offset(struct pipe_context *pipe, 1065 struct pipe_stream_output_target *ptarg, 1066 unsigned index, bool *serialize) 1067{ 1068 struct nvc0_so_target *targ = nvc0_so_target(ptarg); 1069 1070 if (*serialize) { 1071 *serialize = false; 1072 PUSH_SPACE(nvc0_context(pipe)->base.pushbuf, 1); 1073 IMMED_NVC0(nvc0_context(pipe)->base.pushbuf, NVC0_3D(SERIALIZE), 0); 1074 1075 NOUVEAU_DRV_STAT(nouveau_screen(pipe->screen), gpu_serialize_count, 1); 1076 } 1077 1078 nvc0_query(targ->pq)->index = index; 1079 pipe->end_query(pipe, targ->pq); 1080} 1081 1082static void 1083nvc0_so_target_destroy(struct pipe_context *pipe, 1084 struct pipe_stream_output_target *ptarg) 1085{ 1086 struct nvc0_so_target *targ = nvc0_so_target(ptarg); 1087 pipe->destroy_query(pipe, targ->pq); 1088 pipe_resource_reference(&targ->pipe.buffer, NULL); 1089 FREE(targ); 1090} 1091 1092static void 1093nvc0_set_transform_feedback_targets(struct pipe_context *pipe, 1094 unsigned num_targets, 1095 struct pipe_stream_output_target **targets, 1096 const unsigned *offsets) 1097{ 1098 struct nvc0_context *nvc0 = nvc0_context(pipe); 1099 unsigned i; 1100 bool serialize = true; 1101 1102 assert(num_targets <= 4); 1103 1104 for (i = 0; i < num_targets; ++i) { 1105 const bool changed = nvc0->tfbbuf[i] != targets[i]; 1106 const bool append = (offsets[i] == ((unsigned)-1)); 1107 if (!changed && append) 1108 continue; 1109 nvc0->tfbbuf_dirty |= 1 << i; 1110 1111 if (nvc0->tfbbuf[i] && changed) 1112 nvc0_so_target_save_offset(pipe, nvc0->tfbbuf[i], i, &serialize); 1113 1114 if (targets[i] && !append) 1115 nvc0_so_target(targets[i])->clean = true; 1116 1117 pipe_so_target_reference(&nvc0->tfbbuf[i], targets[i]); 1118 } 1119 for (; i < nvc0->num_tfbbufs; ++i) { 1120 if (nvc0->tfbbuf[i]) { 1121 nvc0->tfbbuf_dirty |= 1 << i; 1122 nvc0_so_target_save_offset(pipe, nvc0->tfbbuf[i], i, &serialize); 1123 pipe_so_target_reference(&nvc0->tfbbuf[i], NULL); 1124 } 1125 } 1126 nvc0->num_tfbbufs = num_targets; 1127 1128 if (nvc0->tfbbuf_dirty) { 1129 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TFB); 1130 nvc0->dirty_3d |= NVC0_NEW_3D_TFB_TARGETS; 1131 } 1132} 1133 1134static void 1135nvc0_bind_surfaces_range(struct nvc0_context *nvc0, const unsigned t, 1136 unsigned start, unsigned nr, 1137 struct pipe_surface **psurfaces) 1138{ 1139 const unsigned end = start + nr; 1140 const unsigned mask = ((1 << nr) - 1) << start; 1141 unsigned i; 1142 1143 if (psurfaces) { 1144 for (i = start; i < end; ++i) { 1145 const unsigned p = i - start; 1146 if (psurfaces[p]) 1147 nvc0->surfaces_valid[t] |= (1 << i); 1148 else 1149 nvc0->surfaces_valid[t] &= ~(1 << i); 1150 pipe_surface_reference(&nvc0->surfaces[t][i], psurfaces[p]); 1151 } 1152 } else { 1153 for (i = start; i < end; ++i) 1154 pipe_surface_reference(&nvc0->surfaces[t][i], NULL); 1155 nvc0->surfaces_valid[t] &= ~mask; 1156 } 1157 nvc0->surfaces_dirty[t] |= mask; 1158 1159 if (t == 0) 1160 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF); 1161 else 1162 nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF); 1163} 1164 1165static void 1166nvc0_set_compute_resources(struct pipe_context *pipe, 1167 unsigned start, unsigned nr, 1168 struct pipe_surface **resources) 1169{ 1170 nvc0_bind_surfaces_range(nvc0_context(pipe), 1, start, nr, resources); 1171 1172 nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SURFACES; 1173} 1174 1175static bool 1176nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s, 1177 unsigned start, unsigned nr, 1178 const struct pipe_image_view *pimages) 1179{ 1180 const unsigned end = start + nr; 1181 unsigned mask = 0; 1182 unsigned i; 1183 1184 assert(s < 6); 1185 1186 if (pimages) { 1187 for (i = start; i < end; ++i) { 1188 struct pipe_image_view *img = &nvc0->images[s][i]; 1189 const unsigned p = i - start; 1190 1191 if (img->resource == pimages[p].resource && 1192 img->format == pimages[p].format && 1193 img->access == pimages[p].access) { 1194 if (img->resource == NULL) 1195 continue; 1196 if (img->resource->target == PIPE_BUFFER && 1197 img->u.buf.offset == pimages[p].u.buf.offset && 1198 img->u.buf.size == pimages[p].u.buf.size) 1199 continue; 1200 if (img->resource->target != PIPE_BUFFER && 1201 img->u.tex.first_layer == pimages[p].u.tex.first_layer && 1202 img->u.tex.last_layer == pimages[p].u.tex.last_layer && 1203 img->u.tex.level == pimages[p].u.tex.level) 1204 continue; 1205 } 1206 1207 mask |= (1 << i); 1208 if (pimages[p].resource) 1209 nvc0->images_valid[s] |= (1 << i); 1210 else 1211 nvc0->images_valid[s] &= ~(1 << i); 1212 1213 img->format = pimages[p].format; 1214 img->access = pimages[p].access; 1215 if (pimages[p].resource && pimages[p].resource->target == PIPE_BUFFER) 1216 img->u.buf = pimages[p].u.buf; 1217 else 1218 img->u.tex = pimages[p].u.tex; 1219 1220 pipe_resource_reference( 1221 &img->resource, pimages[p].resource); 1222 1223 if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) { 1224 if (nvc0->images_tic[s][i]) { 1225 struct nv50_tic_entry *old = 1226 nv50_tic_entry(nvc0->images_tic[s][i]); 1227 nvc0_screen_tic_unlock(nvc0->screen, old); 1228 pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL); 1229 } 1230 1231 nvc0->images_tic[s][i] = 1232 gm107_create_texture_view_from_image(&nvc0->base.pipe, 1233 &pimages[p]); 1234 } 1235 } 1236 if (!mask) 1237 return false; 1238 } else { 1239 mask = ((1 << nr) - 1) << start; 1240 if (!(nvc0->images_valid[s] & mask)) 1241 return false; 1242 for (i = start; i < end; ++i) { 1243 pipe_resource_reference(&nvc0->images[s][i].resource, NULL); 1244 if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) { 1245 struct nv50_tic_entry *old = nv50_tic_entry(nvc0->images_tic[s][i]); 1246 if (old) { 1247 nvc0_screen_tic_unlock(nvc0->screen, old); 1248 pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL); 1249 } 1250 } 1251 } 1252 nvc0->images_valid[s] &= ~mask; 1253 } 1254 nvc0->images_dirty[s] |= mask; 1255 1256 if (s == 5) 1257 nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF); 1258 else 1259 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF); 1260 1261 return true; 1262} 1263 1264static void 1265nvc0_set_shader_images(struct pipe_context *pipe, 1266 enum pipe_shader_type shader, 1267 unsigned start, unsigned nr, 1268 const struct pipe_image_view *images) 1269{ 1270 const unsigned s = nvc0_shader_stage(shader); 1271 if (!nvc0_bind_images_range(nvc0_context(pipe), s, start, nr, images)) 1272 return; 1273 1274 if (s == 5) 1275 nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SURFACES; 1276 else 1277 nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_SURFACES; 1278} 1279 1280static bool 1281nvc0_bind_buffers_range(struct nvc0_context *nvc0, const unsigned t, 1282 unsigned start, unsigned nr, 1283 const struct pipe_shader_buffer *pbuffers) 1284{ 1285 const unsigned end = start + nr; 1286 unsigned mask = 0; 1287 unsigned i; 1288 1289 assert(t < 6); 1290 1291 if (pbuffers) { 1292 for (i = start; i < end; ++i) { 1293 struct pipe_shader_buffer *buf = &nvc0->buffers[t][i]; 1294 const unsigned p = i - start; 1295 if (buf->buffer == pbuffers[p].buffer && 1296 buf->buffer_offset == pbuffers[p].buffer_offset && 1297 buf->buffer_size == pbuffers[p].buffer_size) 1298 continue; 1299 1300 mask |= (1 << i); 1301 if (pbuffers[p].buffer) 1302 nvc0->buffers_valid[t] |= (1 << i); 1303 else 1304 nvc0->buffers_valid[t] &= ~(1 << i); 1305 buf->buffer_offset = pbuffers[p].buffer_offset; 1306 buf->buffer_size = pbuffers[p].buffer_size; 1307 pipe_resource_reference(&buf->buffer, pbuffers[p].buffer); 1308 } 1309 if (!mask) 1310 return false; 1311 } else { 1312 mask = ((1 << nr) - 1) << start; 1313 if (!(nvc0->buffers_valid[t] & mask)) 1314 return false; 1315 for (i = start; i < end; ++i) 1316 pipe_resource_reference(&nvc0->buffers[t][i].buffer, NULL); 1317 nvc0->buffers_valid[t] &= ~mask; 1318 } 1319 nvc0->buffers_dirty[t] |= mask; 1320 1321 if (t == 5) 1322 nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_BUF); 1323 else 1324 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_BUF); 1325 1326 return true; 1327} 1328 1329static void 1330nvc0_set_shader_buffers(struct pipe_context *pipe, 1331 enum pipe_shader_type shader, 1332 unsigned start, unsigned nr, 1333 const struct pipe_shader_buffer *buffers, 1334 unsigned writable_bitmask) 1335{ 1336 const unsigned s = nvc0_shader_stage(shader); 1337 if (!nvc0_bind_buffers_range(nvc0_context(pipe), s, start, nr, buffers)) 1338 return; 1339 1340 if (s == 5) 1341 nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_BUFFERS; 1342 else 1343 nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_BUFFERS; 1344} 1345 1346static inline void 1347nvc0_set_global_handle(uint32_t *phandle, struct pipe_resource *res) 1348{ 1349 struct nv04_resource *buf = nv04_resource(res); 1350 if (buf) { 1351 uint64_t limit = (buf->address + buf->base.width0) - 1; 1352 if (limit < (1ULL << 32)) { 1353 *phandle = (uint32_t)buf->address; 1354 } else { 1355 NOUVEAU_ERR("Cannot map into TGSI_RESOURCE_GLOBAL: " 1356 "resource not contained within 32-bit address space !\n"); 1357 *phandle = 0; 1358 } 1359 } else { 1360 *phandle = 0; 1361 } 1362} 1363 1364static void 1365nvc0_set_global_bindings(struct pipe_context *pipe, 1366 unsigned start, unsigned nr, 1367 struct pipe_resource **resources, 1368 uint32_t **handles) 1369{ 1370 struct nvc0_context *nvc0 = nvc0_context(pipe); 1371 struct pipe_resource **ptr; 1372 unsigned i; 1373 const unsigned end = start + nr; 1374 1375 if (nvc0->global_residents.size <= (end * sizeof(struct pipe_resource *))) { 1376 const unsigned old_size = nvc0->global_residents.size; 1377 const unsigned req_size = end * sizeof(struct pipe_resource *); 1378 util_dynarray_resize(&nvc0->global_residents, req_size); 1379 memset((uint8_t *)nvc0->global_residents.data + old_size, 0, 1380 req_size - old_size); 1381 } 1382 1383 if (resources) { 1384 ptr = util_dynarray_element( 1385 &nvc0->global_residents, struct pipe_resource *, start); 1386 for (i = 0; i < nr; ++i) { 1387 pipe_resource_reference(&ptr[i], resources[i]); 1388 nvc0_set_global_handle(handles[i], resources[i]); 1389 } 1390 } else { 1391 ptr = util_dynarray_element( 1392 &nvc0->global_residents, struct pipe_resource *, start); 1393 for (i = 0; i < nr; ++i) 1394 pipe_resource_reference(&ptr[i], NULL); 1395 } 1396 1397 nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_GLOBAL); 1398 1399 nvc0->dirty_cp |= NVC0_NEW_CP_GLOBALS; 1400} 1401 1402void 1403nvc0_init_state_functions(struct nvc0_context *nvc0) 1404{ 1405 struct pipe_context *pipe = &nvc0->base.pipe; 1406 1407 pipe->create_blend_state = nvc0_blend_state_create; 1408 pipe->bind_blend_state = nvc0_blend_state_bind; 1409 pipe->delete_blend_state = nvc0_blend_state_delete; 1410 1411 pipe->create_rasterizer_state = nvc0_rasterizer_state_create; 1412 pipe->bind_rasterizer_state = nvc0_rasterizer_state_bind; 1413 pipe->delete_rasterizer_state = nvc0_rasterizer_state_delete; 1414 1415 pipe->create_depth_stencil_alpha_state = nvc0_zsa_state_create; 1416 pipe->bind_depth_stencil_alpha_state = nvc0_zsa_state_bind; 1417 pipe->delete_depth_stencil_alpha_state = nvc0_zsa_state_delete; 1418 1419 pipe->create_sampler_state = nv50_sampler_state_create; 1420 pipe->delete_sampler_state = nvc0_sampler_state_delete; 1421 pipe->bind_sampler_states = nvc0_bind_sampler_states; 1422 1423 pipe->create_sampler_view = nvc0_create_sampler_view; 1424 pipe->sampler_view_destroy = nvc0_sampler_view_destroy; 1425 pipe->set_sampler_views = nvc0_set_sampler_views; 1426 1427 pipe->create_vs_state = nvc0_vp_state_create; 1428 pipe->create_fs_state = nvc0_fp_state_create; 1429 pipe->create_gs_state = nvc0_gp_state_create; 1430 pipe->create_tcs_state = nvc0_tcp_state_create; 1431 pipe->create_tes_state = nvc0_tep_state_create; 1432 pipe->bind_vs_state = nvc0_vp_state_bind; 1433 pipe->bind_fs_state = nvc0_fp_state_bind; 1434 pipe->bind_gs_state = nvc0_gp_state_bind; 1435 pipe->bind_tcs_state = nvc0_tcp_state_bind; 1436 pipe->bind_tes_state = nvc0_tep_state_bind; 1437 pipe->delete_vs_state = nvc0_sp_state_delete; 1438 pipe->delete_fs_state = nvc0_sp_state_delete; 1439 pipe->delete_gs_state = nvc0_sp_state_delete; 1440 pipe->delete_tcs_state = nvc0_sp_state_delete; 1441 pipe->delete_tes_state = nvc0_sp_state_delete; 1442 1443 pipe->create_compute_state = nvc0_cp_state_create; 1444 pipe->bind_compute_state = nvc0_cp_state_bind; 1445 pipe->delete_compute_state = nvc0_sp_state_delete; 1446 1447 pipe->set_blend_color = nvc0_set_blend_color; 1448 pipe->set_stencil_ref = nvc0_set_stencil_ref; 1449 pipe->set_clip_state = nvc0_set_clip_state; 1450 pipe->set_sample_mask = nvc0_set_sample_mask; 1451 pipe->set_min_samples = nvc0_set_min_samples; 1452 pipe->set_constant_buffer = nvc0_set_constant_buffer; 1453 pipe->set_framebuffer_state = nvc0_set_framebuffer_state; 1454 pipe->set_sample_locations = nvc0_set_sample_locations; 1455 pipe->set_polygon_stipple = nvc0_set_polygon_stipple; 1456 pipe->set_scissor_states = nvc0_set_scissor_states; 1457 pipe->set_viewport_states = nvc0_set_viewport_states; 1458 pipe->set_window_rectangles = nvc0_set_window_rectangles; 1459 pipe->set_tess_state = nvc0_set_tess_state; 1460 1461 pipe->create_vertex_elements_state = nvc0_vertex_state_create; 1462 pipe->delete_vertex_elements_state = nvc0_vertex_state_delete; 1463 pipe->bind_vertex_elements_state = nvc0_vertex_state_bind; 1464 1465 pipe->set_vertex_buffers = nvc0_set_vertex_buffers; 1466 1467 pipe->create_stream_output_target = nvc0_so_target_create; 1468 pipe->stream_output_target_destroy = nvc0_so_target_destroy; 1469 pipe->set_stream_output_targets = nvc0_set_transform_feedback_targets; 1470 1471 pipe->set_global_binding = nvc0_set_global_bindings; 1472 pipe->set_compute_resources = nvc0_set_compute_resources; 1473 pipe->set_shader_images = nvc0_set_shader_images; 1474 pipe->set_shader_buffers = nvc0_set_shader_buffers; 1475 1476 nvc0->sample_mask = ~0; 1477 nvc0->min_samples = 1; 1478 nvc0->default_tess_outer[0] = 1479 nvc0->default_tess_outer[1] = 1480 nvc0->default_tess_outer[2] = 1481 nvc0->default_tess_outer[3] = 1.0; 1482 nvc0->default_tess_inner[0] = 1483 nvc0->default_tess_inner[1] = 1.0; 1484} 1485