1/* 2 * Copyright 2012 Red Hat Inc. 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 * Authors: Ben Skeggs 23 * 24 */ 25 26#include "util/format/u_format.h" 27#include "util/u_helpers.h" 28#include "util/u_inlines.h" 29 30#include "nouveau_gldefs.h" 31#include "nv_object.xml.h" 32#include "nv30/nv30-40_3d.xml.h" 33#include "nv30/nv30_context.h" 34#include "nv30/nv30_winsys.h" 35 36#define NV40_3D_MRT_BLEND_ENABLE 0x0000036c 37 38static void * 39nv30_blend_state_create(struct pipe_context *pipe, 40 const struct pipe_blend_state *cso) 41{ 42 struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; 43 struct nv30_blend_stateobj *so; 44 uint32_t blend[2], cmask[2]; 45 int i; 46 47 so = CALLOC_STRUCT(nv30_blend_stateobj); 48 if (!so) 49 return NULL; 50 so->pipe = *cso; 51 52 if (cso->logicop_enable) { 53 SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 2); 54 SB_DATA (so, 1); 55 SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); 56 } else { 57 SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 1); 58 SB_DATA (so, 0); 59 } 60 61 SB_MTHD30(so, DITHER_ENABLE, 1); 62 SB_DATA (so, cso->dither); 63 64 blend[0] = cso->rt[0].blend_enable; 65 cmask[0] = !!(cso->rt[0].colormask & PIPE_MASK_A) << 24 | 66 !!(cso->rt[0].colormask & PIPE_MASK_R) << 16 | 67 !!(cso->rt[0].colormask & PIPE_MASK_G) << 8 | 68 !!(cso->rt[0].colormask & PIPE_MASK_B); 69 if (cso->independent_blend_enable) { 70 blend[1] = 0; 71 cmask[1] = 0; 72 for (i = 1; i < 4; i++) { 73 blend[1] |= cso->rt[i].blend_enable << i; 74 cmask[1] |= !!(cso->rt[i].colormask & PIPE_MASK_A) << (0 + (i * 4)) | 75 !!(cso->rt[i].colormask & PIPE_MASK_R) << (1 + (i * 4)) | 76 !!(cso->rt[i].colormask & PIPE_MASK_G) << (2 + (i * 4)) | 77 !!(cso->rt[i].colormask & PIPE_MASK_B) << (3 + (i * 4)); 78 } 79 } else { 80 blend[1] = 0x0000000e * (blend[0] & 0x00000001); 81 cmask[1] = 0x00001110 * !!(cmask[0] & 0x01000000); 82 cmask[1] |= 0x00002220 * !!(cmask[0] & 0x00010000); 83 cmask[1] |= 0x00004440 * !!(cmask[0] & 0x00000100); 84 cmask[1] |= 0x00008880 * !!(cmask[0] & 0x00000001); 85 } 86 87 if (eng3d->oclass >= NV40_3D_CLASS) { 88 SB_MTHD40(so, MRT_BLEND_ENABLE, 2); 89 SB_DATA (so, blend[1]); 90 SB_DATA (so, cmask[1]); 91 } 92 93 if (blend[0] || blend[1]) { 94 SB_MTHD30(so, BLEND_FUNC_ENABLE, 3); 95 SB_DATA (so, blend[0]); 96 SB_DATA (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | 97 nvgl_blend_func(cso->rt[0].rgb_src_factor)); 98 SB_DATA (so, (nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16) | 99 nvgl_blend_func(cso->rt[0].rgb_dst_factor)); 100 if (eng3d->oclass < NV40_3D_CLASS) { 101 SB_MTHD30(so, BLEND_EQUATION, 1); 102 SB_DATA (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); 103 } else { 104 SB_MTHD40(so, BLEND_EQUATION, 1); 105 SB_DATA (so, (nvgl_blend_eqn(cso->rt[0].alpha_func) << 16) | 106 nvgl_blend_eqn(cso->rt[0].rgb_func)); 107 } 108 } else { 109 SB_MTHD30(so, BLEND_FUNC_ENABLE, 1); 110 SB_DATA (so, blend[0]); 111 } 112 113 SB_MTHD30(so, COLOR_MASK, 1); 114 SB_DATA (so, cmask[0]); 115 return so; 116} 117 118static void 119nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso) 120{ 121 struct nv30_context *nv30 = nv30_context(pipe); 122 123 nv30->blend = hwcso; 124 nv30->dirty |= NV30_NEW_BLEND; 125} 126 127static void 128nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso) 129{ 130 FREE(hwcso); 131} 132 133static void * 134nv30_rasterizer_state_create(struct pipe_context *pipe, 135 const struct pipe_rasterizer_state *cso) 136{ 137 struct nv30_rasterizer_stateobj *so; 138 139 so = CALLOC_STRUCT(nv30_rasterizer_stateobj); 140 if (!so) 141 return NULL; 142 so->pipe = *cso; 143 144 SB_MTHD30(so, SHADE_MODEL, 1); 145 SB_DATA (so, cso->flatshade ? NV30_3D_SHADE_MODEL_FLAT : 146 NV30_3D_SHADE_MODEL_SMOOTH); 147 148 SB_MTHD30(so, POLYGON_MODE_FRONT, 6); 149 SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); 150 SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); 151 if (cso->cull_face == PIPE_FACE_FRONT_AND_BACK) 152 SB_DATA (so, NV30_3D_CULL_FACE_FRONT_AND_BACK); 153 else 154 if (cso->cull_face == PIPE_FACE_FRONT) 155 SB_DATA (so, NV30_3D_CULL_FACE_FRONT); 156 else 157 SB_DATA (so, NV30_3D_CULL_FACE_BACK); 158 SB_DATA (so, cso->front_ccw ? NV30_3D_FRONT_FACE_CCW : 159 NV30_3D_FRONT_FACE_CW); 160 SB_DATA (so, cso->poly_smooth); 161 SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); 162 163 SB_MTHD30(so, POLYGON_OFFSET_POINT_ENABLE, 3); 164 SB_DATA (so, cso->offset_point); 165 SB_DATA (so, cso->offset_line); 166 SB_DATA (so, cso->offset_tri); 167 if (cso->offset_point || cso->offset_line || cso->offset_tri) { 168 SB_MTHD30(so, POLYGON_OFFSET_FACTOR, 2); 169 SB_DATA (so, fui(cso->offset_scale)); 170 SB_DATA (so, fui(cso->offset_units * 2.0)); 171 } 172 173 SB_MTHD30(so, LINE_WIDTH, 2); 174 SB_DATA (so, (unsigned char)(cso->line_width * 8.0) & 0xff); 175 SB_DATA (so, cso->line_smooth); 176 SB_MTHD30(so, LINE_STIPPLE_ENABLE, 2); 177 SB_DATA (so, cso->line_stipple_enable); 178 SB_DATA (so, (cso->line_stipple_pattern << 16) | 179 cso->line_stipple_factor); 180 181 SB_MTHD30(so, VERTEX_TWO_SIDE_ENABLE, 1); 182 SB_DATA (so, cso->light_twoside); 183 SB_MTHD30(so, POLYGON_STIPPLE_ENABLE, 1); 184 SB_DATA (so, cso->poly_stipple_enable); 185 SB_MTHD30(so, POINT_SIZE, 1); 186 SB_DATA (so, fui(cso->point_size)); 187 SB_MTHD30(so, FLATSHADE_FIRST, 1); 188 SB_DATA (so, cso->flatshade_first); 189 190 SB_MTHD30(so, DEPTH_CONTROL, 1); 191 SB_DATA (so, cso->depth_clip_near ? 0x00000001 : 0x00000010); 192 return so; 193} 194 195static void 196nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) 197{ 198 struct nv30_context *nv30 = nv30_context(pipe); 199 200 nv30->rast = hwcso; 201 nv30->dirty |= NV30_NEW_RASTERIZER; 202} 203 204static void 205nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) 206{ 207 FREE(hwcso); 208} 209 210static void * 211nv30_zsa_state_create(struct pipe_context *pipe, 212 const struct pipe_depth_stencil_alpha_state *cso) 213{ 214 struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; 215 struct nv30_zsa_stateobj *so; 216 217 so = CALLOC_STRUCT(nv30_zsa_stateobj); 218 if (!so) 219 return NULL; 220 so->pipe = *cso; 221 222 SB_MTHD30(so, DEPTH_FUNC, 3); 223 SB_DATA (so, nvgl_comparison_op(cso->depth_func)); 224 SB_DATA (so, cso->depth_writemask); 225 SB_DATA (so, cso->depth_enabled); 226 227 if (eng3d->oclass == NV35_3D_CLASS || eng3d->oclass >= NV40_3D_CLASS) { 228 SB_MTHD35(so, DEPTH_BOUNDS_TEST_ENABLE, 3); 229 SB_DATA (so, cso->depth_bounds_test); 230 SB_DATA (so, fui(cso->depth_bounds_min)); 231 SB_DATA (so, fui(cso->depth_bounds_max)); 232 } 233 234 if (cso->stencil[0].enabled) { 235 SB_MTHD30(so, STENCIL_ENABLE(0), 3); 236 SB_DATA (so, 1); 237 SB_DATA (so, cso->stencil[0].writemask); 238 SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func)); 239 SB_MTHD30(so, STENCIL_FUNC_MASK(0), 4); 240 SB_DATA (so, cso->stencil[0].valuemask); 241 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op)); 242 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); 243 SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); 244 } else { 245 SB_MTHD30(so, STENCIL_ENABLE(0), 2); 246 SB_DATA (so, 0); 247 SB_DATA (so, 0x000000ff); 248 } 249 250 if (cso->stencil[1].enabled) { 251 SB_MTHD30(so, STENCIL_ENABLE(1), 3); 252 SB_DATA (so, 1); 253 SB_DATA (so, cso->stencil[1].writemask); 254 SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func)); 255 SB_MTHD30(so, STENCIL_FUNC_MASK(1), 4); 256 SB_DATA (so, cso->stencil[1].valuemask); 257 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op)); 258 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); 259 SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); 260 } else { 261 SB_MTHD30(so, STENCIL_ENABLE(1), 1); 262 SB_DATA (so, 0); 263 } 264 265 SB_MTHD30(so, ALPHA_FUNC_ENABLE, 3); 266 SB_DATA (so, cso->alpha_enabled ? 1 : 0); 267 SB_DATA (so, nvgl_comparison_op(cso->alpha_func)); 268 SB_DATA (so, float_to_ubyte(cso->alpha_ref_value)); 269 270 return so; 271} 272 273static void 274nv30_zsa_state_bind(struct pipe_context *pipe, void *hwcso) 275{ 276 struct nv30_context *nv30 = nv30_context(pipe); 277 278 nv30->zsa = hwcso; 279 nv30->dirty |= NV30_NEW_ZSA; 280} 281 282static void 283nv30_zsa_state_delete(struct pipe_context *pipe, void *hwcso) 284{ 285 FREE(hwcso); 286} 287 288static void 289nv30_set_blend_color(struct pipe_context *pipe, 290 const struct pipe_blend_color *bcol) 291{ 292 struct nv30_context *nv30 = nv30_context(pipe); 293 294 nv30->blend_colour = *bcol; 295 nv30->dirty |= NV30_NEW_BLEND_COLOUR; 296} 297 298static void 299nv30_set_stencil_ref(struct pipe_context *pipe, 300 const struct pipe_stencil_ref sr) 301{ 302 struct nv30_context *nv30 = nv30_context(pipe); 303 304 nv30->stencil_ref = sr; 305 nv30->dirty |= NV30_NEW_STENCIL_REF; 306} 307 308static void 309nv30_set_clip_state(struct pipe_context *pipe, 310 const struct pipe_clip_state *clip) 311{ 312 struct nv30_context *nv30 = nv30_context(pipe); 313 314 memcpy(nv30->clip.ucp, clip->ucp, sizeof(clip->ucp)); 315 316 nv30->dirty |= NV30_NEW_CLIP; 317} 318 319static void 320nv30_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) 321{ 322 struct nv30_context *nv30 = nv30_context(pipe); 323 324 nv30->sample_mask = sample_mask; 325 nv30->dirty |= NV30_NEW_SAMPLE_MASK; 326} 327 328static void 329nv30_set_constant_buffer(struct pipe_context *pipe, 330 enum pipe_shader_type shader, uint index, 331 bool pass_reference, 332 const struct pipe_constant_buffer *cb) 333{ 334 struct nv30_context *nv30 = nv30_context(pipe); 335 struct pipe_resource *buf = cb ? cb->buffer : NULL; 336 unsigned size; 337 338 if (cb && cb->user_buffer) { 339 buf = nouveau_user_buffer_create(pipe->screen, (void*)cb->user_buffer, 340 cb->buffer_size, 341 PIPE_BIND_CONSTANT_BUFFER); 342 } 343 344 size = 0; 345 if (buf) 346 size = buf->width0 / (4 * sizeof(float)); 347 348 if (shader == PIPE_SHADER_VERTEX) { 349 if (pass_reference) { 350 pipe_resource_reference(&nv30->vertprog.constbuf, NULL); 351 nv30->vertprog.constbuf = buf; 352 } else { 353 pipe_resource_reference(&nv30->vertprog.constbuf, buf); 354 } 355 nv30->vertprog.constbuf_nr = size; 356 nv30->dirty |= NV30_NEW_VERTCONST; 357 } else 358 if (shader == PIPE_SHADER_FRAGMENT) { 359 if (pass_reference) { 360 pipe_resource_reference(&nv30->fragprog.constbuf, NULL); 361 nv30->fragprog.constbuf = buf; 362 } else { 363 pipe_resource_reference(&nv30->fragprog.constbuf, buf); 364 } 365 nv30->fragprog.constbuf_nr = size; 366 nv30->dirty |= NV30_NEW_FRAGCONST; 367 } 368 369 if (cb && cb->user_buffer) { 370 pipe_resource_reference(&buf, NULL); 371 } 372} 373 374static void 375nv30_set_framebuffer_state(struct pipe_context *pipe, 376 const struct pipe_framebuffer_state *fb) 377{ 378 struct nv30_context *nv30 = nv30_context(pipe); 379 380 nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB); 381 382 nv30->framebuffer = *fb; 383 nv30->dirty |= NV30_NEW_FRAMEBUFFER; 384 385 /* Hardware can't handle different swizzled-ness or different blocksizes 386 * for zs and cbufs. If both are supplied and something doesn't match, 387 * blank out the zs for now so that at least *some* rendering can occur. 388 */ 389 if (fb->nr_cbufs > 0 && fb->zsbuf) { 390 struct nv30_miptree *color_mt = nv30_miptree(fb->cbufs[0]->texture); 391 struct nv30_miptree *zeta_mt = nv30_miptree(fb->zsbuf->texture); 392 393 if (color_mt->swizzled != zeta_mt->swizzled || 394 (color_mt->swizzled && 395 (util_format_get_blocksize(fb->zsbuf->format) > 2) != 396 (util_format_get_blocksize(fb->cbufs[0]->format) > 2))) { 397 nv30->framebuffer.zsbuf = NULL; 398 debug_printf("Mismatched color and zeta formats, ignoring zeta.\n"); 399 } 400 } 401} 402 403static void 404nv30_set_polygon_stipple(struct pipe_context *pipe, 405 const struct pipe_poly_stipple *stipple) 406{ 407 struct nv30_context *nv30 = nv30_context(pipe); 408 409 nv30->stipple = *stipple; 410 nv30->dirty |= NV30_NEW_STIPPLE; 411} 412 413static void 414nv30_set_scissor_states(struct pipe_context *pipe, 415 unsigned start_slot, 416 unsigned num_viewports, 417 const struct pipe_scissor_state *scissor) 418{ 419 struct nv30_context *nv30 = nv30_context(pipe); 420 421 nv30->scissor = *scissor; 422 nv30->dirty |= NV30_NEW_SCISSOR; 423} 424 425static void 426nv30_set_viewport_states(struct pipe_context *pipe, 427 unsigned start_slot, 428 unsigned num_viewports, 429 const struct pipe_viewport_state *vpt) 430{ 431 struct nv30_context *nv30 = nv30_context(pipe); 432 433 nv30->viewport = *vpt; 434 nv30->dirty |= NV30_NEW_VIEWPORT; 435} 436 437static void 438nv30_set_vertex_buffers(struct pipe_context *pipe, 439 unsigned start_slot, unsigned count, 440 unsigned unbind_num_trailing_slots, 441 bool take_ownership, 442 const struct pipe_vertex_buffer *vb) 443{ 444 struct nv30_context *nv30 = nv30_context(pipe); 445 446 nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF); 447 448 util_set_vertex_buffers_count(nv30->vtxbuf, &nv30->num_vtxbufs, 449 vb, start_slot, count, 450 unbind_num_trailing_slots, 451 take_ownership); 452 453 nv30->dirty |= NV30_NEW_ARRAYS; 454} 455 456void 457nv30_state_init(struct pipe_context *pipe) 458{ 459 pipe->create_blend_state = nv30_blend_state_create; 460 pipe->bind_blend_state = nv30_blend_state_bind; 461 pipe->delete_blend_state = nv30_blend_state_delete; 462 463 pipe->create_rasterizer_state = nv30_rasterizer_state_create; 464 pipe->bind_rasterizer_state = nv30_rasterizer_state_bind; 465 pipe->delete_rasterizer_state = nv30_rasterizer_state_delete; 466 467 pipe->create_depth_stencil_alpha_state = nv30_zsa_state_create; 468 pipe->bind_depth_stencil_alpha_state = nv30_zsa_state_bind; 469 pipe->delete_depth_stencil_alpha_state = nv30_zsa_state_delete; 470 471 pipe->set_blend_color = nv30_set_blend_color; 472 pipe->set_stencil_ref = nv30_set_stencil_ref; 473 pipe->set_clip_state = nv30_set_clip_state; 474 pipe->set_sample_mask = nv30_set_sample_mask; 475 pipe->set_constant_buffer = nv30_set_constant_buffer; 476 pipe->set_framebuffer_state = nv30_set_framebuffer_state; 477 pipe->set_polygon_stipple = nv30_set_polygon_stipple; 478 pipe->set_scissor_states = nv30_set_scissor_states; 479 pipe->set_viewport_states = nv30_set_viewport_states; 480 481 pipe->set_vertex_buffers = nv30_set_vertex_buffers; 482} 483